[ossim-planet] 01/06: Imported Upstream version 1.8.20.3+ds
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Sat Jun 4 12:57:19 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository ossim-planet.
commit 743f9befdf0d01bce3d6a0dc44e64b4727f690fe
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Fri Jun 3 23:35:35 2016 +0200
Imported Upstream version 1.8.20.3+ds
---
ossimPlanet/AUTHORS.txt | 6 +
ossimPlanet/CMakeLists.txt | 122 +
ossimPlanet/Doxyfile | 1541 ++++++++++
ossimPlanet/GNUmakefile.old | 12 +
ossimPlanet/LICENSE.txt | 76 +
ossimPlanet/Make/cygwin_plugin_def | 15 +
ossimPlanet/Make/dependencies | 9 +
ossimPlanet/Make/distrules | 16 +
ossimPlanet/Make/dolink.sh | 66 +
ossimPlanet/Make/help.sh | 155 +
ossimPlanet/Make/helprules | 11 +
ossimPlanet/Make/instexamplesrc | 107 +
ossimPlanet/Make/instrules | 149 +
ossimPlanet/Make/makedefs | 597 ++++
ossimPlanet/Make/makedirdefs | 26 +
ossimPlanet/Make/makedirrules | 6 +
ossimPlanet/Make/makeinnosetup | 152 +
ossimPlanet/Make/makeirixdist | 158 +
ossimPlanet/Make/makepkg | 220 ++
ossimPlanet/Make/makerpms | 200 ++
ossimPlanet/Make/makerules | 199 ++
ossimPlanet/Make/maketoprule | 20 +
ossimPlanet/Make/versionrules | 16 +
ossimPlanet/README.txt | 12 +
.../apps/ossimplanet-chip/ossimplanet-chip.cpp | 496 +++
ossimPlanet/binds.act | 26 +
ossimPlanet/examples/GNUmakefile | 11 +
ossimPlanet/examples/ossimplanetinfo/GNUmakefile | 20 +
.../examples/ossimplanetinfo/ossimplanetinfo.cpp | 93 +
.../ossimplanetinfo/ossimplanetinfo.vcproj | 208 ++
ossimPlanet/examples/ossimplanetklv/GNUmakefile | 20 +
.../examples/ossimplanetklv/ossimplanetklv.cpp | 179 ++
ossimPlanet/examples/ossimplanettest/GNUmakefile | 20 +
.../examples/ossimplanettest/ossimplanettest.cpp | 1657 ++++++++++
ossimPlanet/examples/ossimplanetviewer/GNUmakefile | 21 +
.../examples/ossimplanetviewer/archive_manager.kwl | 36 +
.../examples/ossimplanetviewer/opvLoadModel.cpp | 354 +++
.../examples/ossimplanetviewer/opvLoadModel.h | 9 +
.../ossimplanetviewer/ossimplanetviewer.cpp | 743 +++++
.../ossimplanetviewer/ossimplanetviewer.vcproj | 212 ++
ossimPlanet/examples/ossimplanetviewer/readme.txt | 9 +
ossimPlanet/include/ossimPlanet/compiler.h | 470 +++
ossimPlanet/include/ossimPlanet/ioapi.h | 75 +
ossimPlanet/include/ossimPlanet/iochannel.h | 180 ++
ossimPlanet/include/ossimPlanet/iowin32.h | 21 +
ossimPlanet/include/ossimPlanet/mkUtils.h | 332 ++
ossimPlanet/include/ossimPlanet/net.h | 12 +
ossimPlanet/include/ossimPlanet/netBuffer.h | 234 ++
ossimPlanet/include/ossimPlanet/netChannel.h | 116 +
ossimPlanet/include/ossimPlanet/netChat.h | 86 +
ossimPlanet/include/ossimPlanet/netMessage.h | 294 ++
ossimPlanet/include/ossimPlanet/netMonitor.h | 106 +
ossimPlanet/include/ossimPlanet/netSocket.h | 115 +
ossimPlanet/include/ossimPlanet/ossimPlanet.h | 135 +
.../include/ossimPlanet/ossimPlanetAction.h | 161 +
.../ossimPlanet/ossimPlanetActionReceiver.h | 39 +
.../include/ossimPlanet/ossimPlanetActionRouter.h | 247 ++
.../ossimPlanet/ossimPlanetAnimatedPointModel.h | 68 +
.../include/ossimPlanet/ossimPlanetAnimationPath.h | 92 +
.../ossimPlanet/ossimPlanetAnnotationLayer.h | 83 +
.../ossimPlanet/ossimPlanetAnnotationLayerNode.h | 453 +++
ossimPlanet/include/ossimPlanet/ossimPlanetApi.h | 770 +++++
.../include/ossimPlanet/ossimPlanetArchive.h | 37 +
.../ossimPlanet/ossimPlanetArchiveMapping.h | 29 +
.../include/ossimPlanet/ossimPlanetBillboardIcon.h | 75 +
.../include/ossimPlanet/ossimPlanetBoundingBox.h | 234 ++
ossimPlanet/include/ossimPlanet/ossimPlanetCache.h | 178 ++
.../ossimPlanet/ossimPlanetCacheTextureLayer.h | 79 +
.../include/ossimPlanet/ossimPlanetCallback.h | 110 +
.../include/ossimPlanet/ossimPlanetClientThread.h | 94 +
.../include/ossimPlanet/ossimPlanetCloudLayer.h | 231 ++
.../include/ossimPlanet/ossimPlanetCompass.h | 103 +
.../include/ossimPlanet/ossimPlanetConstants.h | 111 +
.../include/ossimPlanet/ossimPlanetCubeGrid.h | 37 +
.../include/ossimPlanet/ossimPlanetDatabasePager.h | 67 +
.../ossimPlanet/ossimPlanetDepthPartitionNode.h | 104 +
.../ossimPlanetDestinationCommandAction.h | 85 +
.../ossimPlanet/ossimPlanetDistanceAccumulator.h | 116 +
.../ossimPlanet/ossimPlanetDtedElevationDatabase.h | 85 +
.../ossimPlanet/ossimPlanetElevationDatabase.h | 69 +
.../ossimPlanetElevationDatabaseGroup.h | 58 +
.../ossimPlanet/ossimPlanetElevationFactory.h | 12 +
.../include/ossimPlanet/ossimPlanetElevationGrid.h | 60 +
.../ossimPlanet/ossimPlanetElevationRegistry.h | 36 +
.../include/ossimPlanet/ossimPlanetEphemeris.h | 392 +++
.../include/ossimPlanet/ossimPlanetExport.h | 60 +
.../include/ossimPlanet/ossimPlanetExtents.h | 351 +++
.../include/ossimPlanet/ossimPlanetFadeText.h | 77 +
.../ossimPlanetGeneralRasterElevationDatabase.h | 63 +
.../include/ossimPlanet/ossimPlanetGeoRefModel.h | 370 +++
.../include/ossimPlanet/ossimPlanetGeocoder.h | 82 +
ossimPlanet/include/ossimPlanet/ossimPlanetGrid.h | 310 ++
.../include/ossimPlanet/ossimPlanetGridUtility.h | 166 +
.../include/ossimPlanet/ossimPlanetIconGeom.h | 44 +
ossimPlanet/include/ossimPlanet/ossimPlanetId.h | 79 +
.../include/ossimPlanet/ossimPlanetIdManager.h | 15 +
.../include/ossimPlanet/ossimPlanetIdolBridge.h | 105 +
.../include/ossimPlanet/ossimPlanetIdolLayer.h | 140 +
ossimPlanet/include/ossimPlanet/ossimPlanetImage.h | 186 ++
.../include/ossimPlanet/ossimPlanetInputDevice.h | 20 +
.../ossimPlanet/ossimPlanetInteractionController.h | 154 +
.../ossimPlanet/ossimPlanetIntersectUserData.h | 27 +
ossimPlanet/include/ossimPlanet/ossimPlanetIo.h | 156 +
.../ossimPlanet/ossimPlanetIoMessageHandler.h | 40 +
.../ossimPlanetIoRoutableMessageHandler.h | 15 +
.../include/ossimPlanet/ossimPlanetIoSocket.h | 125 +
.../ossimPlanet/ossimPlanetIoSocketServerChannel.h | 98 +
.../include/ossimPlanet/ossimPlanetIoThread.h | 76 +
.../include/ossimPlanet/ossimPlanetJpegImage.h | 24 +
ossimPlanet/include/ossimPlanet/ossimPlanetKml.h | 2553 ++++++++++++++++
.../include/ossimPlanet/ossimPlanetKmlLayer.h | 201 ++
.../include/ossimPlanet/ossimPlanetKmlLayerNode.h | 49 +
.../ossimPlanet/ossimPlanetKmlNetworkLinkNode.h | 18 +
.../ossimPlanet/ossimPlanetKmlPlacemarkNode.h | 72 +
.../ossimPlanet/ossimPlanetKmlReaderWriter.h | 16 +
.../ossimPlanet/ossimPlanetKmlScreenOverlayNode.h | 49 +
.../include/ossimPlanet/ossimPlanetLabelGeom.h | 77 +
ossimPlanet/include/ossimPlanet/ossimPlanetLand.h | 181 ++
.../include/ossimPlanet/ossimPlanetLandCache.h | 114 +
.../ossimPlanet/ossimPlanetLandCullCallback.h | 55 +
.../include/ossimPlanet/ossimPlanetLandNode.h | 115 +
.../ossimPlanet/ossimPlanetLandNormalType.h | 10 +
.../ossimPlanet/ossimPlanetLandReaderWriter.h | 202 ++
.../ossimPlanet/ossimPlanetLandTextureRequest.h | 226 ++
.../include/ossimPlanet/ossimPlanetLandTreeNode.h | 26 +
.../include/ossimPlanet/ossimPlanetLatLonHud.h | 86 +
ossimPlanet/include/ossimPlanet/ossimPlanetLayer.h | 58 +
.../include/ossimPlanet/ossimPlanetLayerFactory.h | 21 +
.../ossimPlanet/ossimPlanetLayerFactoryBase.h | 15 +
.../include/ossimPlanet/ossimPlanetLayerRegistry.h | 39 +
.../include/ossimPlanet/ossimPlanetLookAt.h | 230 ++
.../ossimPlanet/ossimPlanetLsrSpaceTransform.h | 363 +++
.../ossimPlanet/ossimPlanetManipulator.back | 125 +
.../include/ossimPlanet/ossimPlanetManipulator.h | 309 ++
.../include/ossimPlanet/ossimPlanetMessage.h | 48 +
.../include/ossimPlanet/ossimPlanetNavigator.h | 277 ++
.../ossimPlanet/ossimPlanetNetworkConnection.h | 41 +
ossimPlanet/include/ossimPlanet/ossimPlanetNode.h | 255 ++
.../include/ossimPlanet/ossimPlanetNodeFactory.h | 17 +
.../ossimPlanet/ossimPlanetNodeFactoryBase.h | 18 +
.../include/ossimPlanet/ossimPlanetNodeRegistry.h | 30 +
.../include/ossimPlanet/ossimPlanetOperation.h | 422 +++
.../ossimPlanet/ossimPlanetOrthoFlatLandNode.h | 26 +
.../ossimPlanetOssimElevationDatabase.h | 56 +
.../include/ossimPlanet/ossimPlanetOssimImage.h | 21 +
.../ossimPlanet/ossimPlanetOssimImageLayer.h | 370 +++
.../include/ossimPlanet/ossimPlanetPagedLandLod.h | 199 ++
.../ossimPlanetPagedLandLodRefreshType.h | 16 +
.../ossimPlanet/ossimPlanetPagedRequestNode.h | 70 +
.../include/ossimPlanet/ossimPlanetPlaneGrid.h | 28 +
.../include/ossimPlanet/ossimPlanetPointModel.h | 150 +
.../ossimPlanetPredatorVideoLayerNode.h | 264 ++
.../include/ossimPlanet/ossimPlanetPrimaryBody.h | 130 +
.../ossimPlanet/ossimPlanetReentrantMutex.h | 110 +
.../include/ossimPlanet/ossimPlanetRefBlock.h | 15 +
.../include/ossimPlanet/ossimPlanetSceneView.h | 37 +
.../ossimPlanet/ossimPlanetServerMessageHandler.h | 30 +
.../include/ossimPlanet/ossimPlanetServerThread.h | 75 +
ossimPlanet/include/ossimPlanet/ossimPlanetSetup.h | 8 +
.../ossimPlanet/ossimPlanetShaderProgramSetup.h | 86 +
.../ossimPlanetSocketNetworkConnection.h | 68 +
.../include/ossimPlanet/ossimPlanetSousaLayer.h | 97 +
.../ossimPlanet/ossimPlanetSrtmElevationDatabase.h | 65 +
.../ossimPlanetStandardTextureLayerFactory.h | 30 +
.../include/ossimPlanet/ossimPlanetTerrain.h | 435 +++
.../ossimPlanetTerrainGeometryTechnique.h | 255 ++
.../include/ossimPlanet/ossimPlanetTerrainLayer.h | 191 ++
.../ossimPlanet/ossimPlanetTerrainTechnique.h | 170 ++
.../include/ossimPlanet/ossimPlanetTerrainTile.h | 223 ++
.../include/ossimPlanet/ossimPlanetTerrainTileId.h | 76 +
.../include/ossimPlanet/ossimPlanetTexture2D.h | 34 +
.../include/ossimPlanet/ossimPlanetTextureLayer.h | 380 +++
.../ossimPlanet/ossimPlanetTextureLayerFactory.h | 19 +
.../ossimPlanet/ossimPlanetTextureLayerGroup.h | 115 +
.../ossimPlanet/ossimPlanetTextureLayerRegistry.h | 40 +
.../include/ossimPlanet/ossimPlanetThread.h | 30 +
.../include/ossimPlanet/ossimPlanetThreadImp.h | 38 +
.../include/ossimPlanet/ossimPlanetThreadPool.h | 32 +
.../include/ossimPlanet/ossimPlanetTileRequest.h | 256 ++
.../include/ossimPlanet/ossimPlanetUtility.h | 29 +
.../include/ossimPlanet/ossimPlanetVideoLayer.h | 61 +
.../ossimPlanet/ossimPlanetVideoLayerNode.h | 72 +
.../ossimPlanet/ossimPlanetViewMatrixBuilder.h | 680 +++++
.../include/ossimPlanet/ossimPlanetViewer.h | 487 +++
.../include/ossimPlanet/ossimPlanetVisitors.h | 140 +
.../include/ossimPlanet/ossimPlanetWmsClient.h | 99 +
.../include/ossimPlanet/ossimPlanetWmsImageLayer.h | 128 +
.../include/ossimPlanet/ossimPlanetXmlAction.h | 81 +
.../include/ossimPlanet/ossimPlanetYahooGeocoder.h | 23 +
ossimPlanet/include/ossimPlanet/sg_file.h | 101 +
ossimPlanet/include/ossimPlanet/sg_socket.h | 181 ++
ossimPlanet/include/ossimPlanet/sg_socket_udp.h | 137 +
ossimPlanet/include/ossimPlanet/ul.h | 868 ++++++
ossimPlanet/include/ossimPlanet/ulLocal.h | 52 +
ossimPlanet/include/ossimPlanet/ulRTTI.h | 420 +++
ossimPlanet/include/ossimPlanet/unzip.h | 354 +++
ossimPlanet/include/ossimPlanet/zip.h | 235 ++
ossimPlanet/projects/vs2005/ossimPlanet.sln | 34 +
ossimPlanet/projects/vs2005/ossimPlanet.vcproj | 1381 +++++++++
ossimPlanet/schema/AnimationPath.xsd | 51 +
ossimPlanet/schema/ossimPlanet.xsd | 447 +++
ossimPlanet/src/GNUmakefile | 7 +
ossimPlanet/src/ossimPlanet/GNUmakefile | 144 +
ossimPlanet/src/ossimPlanet/crypt.h | 132 +
ossimPlanet/src/ossimPlanet/ioapi.c | 177 ++
ossimPlanet/src/ossimPlanet/iochannel.cpp | 84 +
ossimPlanet/src/ossimPlanet/iowin32.c | 270 ++
ossimPlanet/src/ossimPlanet/mkUtils.cpp | 471 +++
ossimPlanet/src/ossimPlanet/netBuffer.cpp | 69 +
ossimPlanet/src/ossimPlanet/netChannel.cpp | 279 ++
ossimPlanet/src/ossimPlanet/netChat.cpp | 125 +
ossimPlanet/src/ossimPlanet/netMessage.cpp | 50 +
ossimPlanet/src/ossimPlanet/netMonitor.cpp | 180 ++
ossimPlanet/src/ossimPlanet/netSocket.cpp | 503 +++
ossimPlanet/src/ossimPlanet/ossimPlanet.cpp | 507 +++
ossimPlanet/src/ossimPlanet/ossimPlanetAction.cpp | 55 +
.../src/ossimPlanet/ossimPlanetActionReceiver.cpp | 31 +
.../src/ossimPlanet/ossimPlanetActionRouter.cpp | 374 +++
.../ossimPlanet/ossimPlanetAnimatedPointModel.cpp | 307 ++
.../src/ossimPlanet/ossimPlanetAnimationPath.cpp | 407 +++
.../src/ossimPlanet/ossimPlanetAnnotationLayer.cpp | 246 ++
.../ossimPlanet/ossimPlanetAnnotationLayerNode.cpp | 557 ++++
ossimPlanet/src/ossimPlanet/ossimPlanetApi.cpp | 1135 +++++++
ossimPlanet/src/ossimPlanet/ossimPlanetArchive.cpp | 199 ++
.../src/ossimPlanet/ossimPlanetArchiveMapping.cpp | 36 +
.../src/ossimPlanet/ossimPlanetBillboardIcon.cpp | 129 +
.../src/ossimPlanet/ossimPlanetBoundingBox.cpp | 56 +
ossimPlanet/src/ossimPlanet/ossimPlanetCache.cpp | 195 ++
.../ossimPlanet/ossimPlanetCacheTextureLayer.cpp | 283 ++
.../src/ossimPlanet/ossimPlanetClientThread.cpp | 360 +++
.../src/ossimPlanet/ossimPlanetCloudLayer.cpp | 666 ++++
ossimPlanet/src/ossimPlanet/ossimPlanetCompass.cpp | 638 ++++
.../src/ossimPlanet/ossimPlanetCubeGrid.cpp | 221 ++
.../src/ossimPlanet/ossimPlanetDatabasePager.cpp | 583 ++++
.../ossimPlanet/ossimPlanetDepthPartitionNode.cpp | 272 ++
.../ossimPlanetDestinationCommandAction.cpp | 97 +
.../ossimPlanet/ossimPlanetDistanceAccumulator.cpp | 402 +++
.../ossimPlanetDtedElevationDatabase.cpp | 715 +++++
.../ossimPlanet/ossimPlanetElevationDatabase.cpp | 92 +
.../ossimPlanetElevationDatabaseGroup.cpp | 518 ++++
.../ossimPlanet/ossimPlanetElevationFactory.cpp | 49 +
.../src/ossimPlanet/ossimPlanetElevationGrid.cpp | 174 ++
.../ossimPlanet/ossimPlanetElevationRegistry.cpp | 61 +
.../src/ossimPlanet/ossimPlanetEphemeris.cpp | 2508 +++++++++++++++
.../src/ossimPlanet/ossimPlanetFadeText.cpp | 471 +++
.../ossimPlanetGeneralRasterElevationDatabase.cpp | 616 ++++
.../src/ossimPlanet/ossimPlanetGeocoder.cpp | 81 +
ossimPlanet/src/ossimPlanet/ossimPlanetGrid.cpp | 1100 +++++++
.../src/ossimPlanet/ossimPlanetGridUtility.cpp | 526 ++++
.../src/ossimPlanet/ossimPlanetIconGeom.cpp | 157 +
ossimPlanet/src/ossimPlanet/ossimPlanetId.cpp | 8 +
.../src/ossimPlanet/ossimPlanetIdManager.cpp | 12 +
ossimPlanet/src/ossimPlanet/ossimPlanetImage.cpp | 1157 +++++++
.../ossimPlanetInteractionController.cpp | 338 ++
.../ossimPlanetIoRoutableMessageHandler.cpp | 20 +
.../src/ossimPlanet/ossimPlanetIoSocket.cpp | 665 ++++
.../ossimPlanetIoSocketServerChannel.cpp | 330 ++
.../src/ossimPlanet/ossimPlanetIoThread.cpp | 748 +++++
.../src/ossimPlanet/ossimPlanetJpegImage.cpp | 363 +++
ossimPlanet/src/ossimPlanet/ossimPlanetKml.cpp | 2818 +++++++++++++++++
.../src/ossimPlanet/ossimPlanetKmlLayer.cpp | 504 +++
.../src/ossimPlanet/ossimPlanetKmlLayerNode.cpp | 50 +
.../ossimPlanet/ossimPlanetKmlNetworkLinkNode.cpp | 108 +
.../ossimPlanet/ossimPlanetKmlPlacemarkNode.cpp | 1176 +++++++
.../ossimPlanetKmlScreenOverlayNode.cpp | 359 +++
.../src/ossimPlanet/ossimPlanetLabelGeom.cpp | 166 +
ossimPlanet/src/ossimPlanet/ossimPlanetLand.cpp | 1695 +++++++++++
.../src/ossimPlanet/ossimPlanetLandCache.cpp | 290 ++
.../ossimPlanet/ossimPlanetLandCullCallback.cpp | 481 +++
.../ossimPlanet/ossimPlanetLandReaderWriter.cpp | 1864 ++++++++++++
.../src/ossimPlanet/ossimPlanetLatLonHud.cpp | 506 +++
ossimPlanet/src/ossimPlanet/ossimPlanetLayer.cpp | 226 ++
.../src/ossimPlanet/ossimPlanetLayerFactory.cpp | 63 +
.../src/ossimPlanet/ossimPlanetLayerRegistry.cpp | 89 +
ossimPlanet/src/ossimPlanet/ossimPlanetLookAt.cpp | 48 +
.../ossimPlanet/ossimPlanetLsrSpaceTransform.cpp | 210 ++
.../src/ossimPlanet/ossimPlanetManipulator.cpp | 806 +++++
.../src/ossimPlanet/ossimPlanetNavigator.cpp | 1460 +++++++++
ossimPlanet/src/ossimPlanet/ossimPlanetNode.cpp | 350 +++
.../src/ossimPlanet/ossimPlanetNodeFactory.cpp | 35 +
.../src/ossimPlanet/ossimPlanetNodeRegistry.cpp | 84 +
.../src/ossimPlanet/ossimPlanetOperation.cpp | 652 ++++
.../ossimPlanetOssimElevationDatabase.cpp | 355 +++
.../src/ossimPlanet/ossimPlanetOssimImage.cpp | 43 +
.../src/ossimPlanet/ossimPlanetOssimImageLayer.cpp | 1374 +++++++++
.../src/ossimPlanet/ossimPlanetPagedLandLod.cpp | 505 +++
.../src/ossimPlanet/ossimPlanetPlaneGrid.cpp | 73 +
.../src/ossimPlanet/ossimPlanetPointModel.cpp | 115 +
.../ossimPlanetPredatorVideoLayerNode.cpp | 936 ++++++
.../src/ossimPlanet/ossimPlanetSceneView.cpp | 214 ++
.../src/ossimPlanet/ossimPlanetServerThread.cpp | 310 ++
.../ossimPlanet/ossimPlanetShaderProgramSetup.cpp | 17 +
.../ossimPlanetSocketNetworkConnection.cpp | 186 ++
.../src/ossimPlanet/ossimPlanetSousaLayer.cpp | 749 +++++
.../ossimPlanetSrtmElevationDatabase.cpp | 804 +++++
.../ossimPlanetStandardTextureLayerFactory.cpp | 207 ++
ossimPlanet/src/ossimPlanet/ossimPlanetTerrain.cpp | 1716 +++++++++++
.../ossimPlanetTerrainGeometryTechnique.cpp | 1744 +++++++++++
.../src/ossimPlanet/ossimPlanetTerrainLayer.cpp | 1 +
.../ossimPlanet/ossimPlanetTerrainTechnique.cpp | 343 +++
.../src/ossimPlanet/ossimPlanetTerrainTile.cpp | 359 +++
.../src/ossimPlanet/ossimPlanetTexture2D.cpp | 83 +
.../src/ossimPlanet/ossimPlanetTextureLayer.cpp | 1641 ++++++++++
.../ossimPlanet/ossimPlanetTextureLayerGroup.cpp | 1086 +++++++
.../ossimPlanetTextureLayerRegistry.cpp | 105 +
ossimPlanet/src/ossimPlanet/ossimPlanetThread.cpp | 77 +
.../src/ossimPlanet/ossimPlanetThreadImp.cpp | 33 +
.../src/ossimPlanet/ossimPlanetThreadPool.cpp | 84 +
.../src/ossimPlanet/ossimPlanetTileRequest.cpp | 864 ++++++
ossimPlanet/src/ossimPlanet/ossimPlanetUtility.cpp | 129 +
.../src/ossimPlanet/ossimPlanetVideoLayer.cpp | 46 +
.../ossimPlanet/ossimPlanetViewMatrixBuilder.cpp | 615 ++++
ossimPlanet/src/ossimPlanet/ossimPlanetViewer.cpp | 1127 +++++++
.../src/ossimPlanet/ossimPlanetVisitors.cpp | 112 +
.../src/ossimPlanet/ossimPlanetWmsClient.cpp | 246 ++
.../src/ossimPlanet/ossimPlanetWmsImageLayer.cpp | 922 ++++++
.../src/ossimPlanet/ossimPlanetXmlAction.cpp | 225 ++
.../src/ossimPlanet/ossimPlanetYahooGeocoder.cpp | 87 +
ossimPlanet/src/ossimPlanet/sg_file.cpp | 143 +
ossimPlanet/src/ossimPlanet/sg_socket.cpp | 494 +++
ossimPlanet/src/ossimPlanet/sg_socket_udp.cpp | 200 ++
ossimPlanet/src/ossimPlanet/ul.cpp | 544 ++++
ossimPlanet/src/ossimPlanet/ulClock.cpp | 117 +
ossimPlanet/src/ossimPlanet/ulError.cpp | 90 +
ossimPlanet/src/ossimPlanet/ulLinkedList.cpp | 272 ++
ossimPlanet/src/ossimPlanet/ulList.cpp | 109 +
ossimPlanet/src/ossimPlanet/ulRTTI.cpp | 109 +
ossimPlanet/src/ossimPlanet/unzip.c | 1630 ++++++++++
ossimPlanet/src/ossimPlanet/zip.c | 1219 ++++++++
.../ossimPlanet/English.lproj/InfoPlist.strings | Bin 0 -> 152 bytes
ossimPlanet/xcode/ossimPlanet/Info.plist | 26 +
.../ossimPlanet.xcodeproj/project.pbxproj | 3219 ++++++++++++++++++++
332 files changed, 94604 insertions(+)
diff --git a/ossimPlanet/AUTHORS.txt b/ossimPlanet/AUTHORS.txt
new file mode 100644
index 0000000..98be0a4
--- /dev/null
+++ b/ossimPlanet/AUTHORS.txt
@@ -0,0 +1,6 @@
+// $Id: AUTHORS.txt 9332 2006-07-31 14:55:34Z gpotts $
+Garrett Potts <gpotts at intelligence-data.com>
+
+Norman Vine
+
+Eric Sokolowski
diff --git a/ossimPlanet/CMakeLists.txt b/ossimPlanet/CMakeLists.txt
new file mode 100644
index 0000000..ba9ff0a
--- /dev/null
+++ b/ossimPlanet/CMakeLists.txt
@@ -0,0 +1,122 @@
+PROJECT(ossimPlanet)
+MESSAGE("**********************Setting up ossimPlanet********************")
+INCLUDE(OssimVersion)
+INCLUDE(OssimUtilities)
+INCLUDE(OssimCommonVariables)
+
+OPTION(OSSIMPLANET_ENABLE_EPHEMERIS "Set to ON enable ephemeris support if GPSTK is found. Use OFF to not enable ephemeris." ON)
+
+IF(NOT APPLE)
+ cmake_minimum_required(VERSION 2.6)
+ELSE(NOT APPLE)
+ cmake_minimum_required(VERSION 2.8)
+ENDIF(NOT APPLE)
+
+find_package(OpenThreads)
+find_package(ossim)
+find_package(ossimPredator)
+find_package(GPSTK)
+find_package(JPEG)
+find_package(OSG)
+find_package(WMS)
+find_package(ZLIB)
+find_package(OpenGL)
+find_package(FFmpeg)
+find_package(Regex)
+
+MESSAGE( STATUS "OSSIM_INCLUDE_DIR = ${OSSIM_INCLUDE_DIR}")
+MESSAGE( STATUS "OSSIM_LIBRARIES = ${OSSIM_LIBRARIES}")
+MESSAGE( STATUS "OPENGL_INCLUDE_DIR = ${OPENGL_INCLUDE_DIR}")
+MESSAGE( STATUS "OPENGL_LIBRARIES = ${OPENGL_LIBRARIES}")
+MESSAGE( STATUS "OSSIM_LIBRARIES = ${OSSIM_LIBRARIES}")
+MESSAGE( STATUS "OSSIMPREDATOR_LIBRARIES = ${OSSIMPREDATOR_LIBRARIES}")
+MESSAGE( STATUS "OSSIMPREDATOR_INCLUDE_DIR = ${OSSIMPREDATOR_INCLUDE_DIR}")
+MESSAGE( STATUS "OPENTHREADS_LIBRARY = ${OPENTHREADS_LIBRARY}")
+MESSAGE( STATUS "OPENTHREADS_INCLUDE_DIR = ${OPENTHREADS_INCLUDE_DIR}")
+MESSAGE( STATUS "FFMPEG_LIBRARIES = ${FFMPEG_LIBRARIES}")
+MESSAGE( STATUS "FFMPEG_INCLUDE_DIRS = ${FFMPEG_INCLUDE_DIRS}")
+MESSAGE( STATUS "WMS_LIBRARY = ${WMS_LIBRARY}")
+MESSAGE( STATUS "WMS_INCLUDE_DIR = ${WMS_INCLUDE_DIR}")
+
+MESSAGE( STATUS "OSG_LIBRARY = ${OSG_LIBRARY}")
+MESSAGE( STATUS "OSG_INCLUDE_DIR = ${OSG_INCLUDE_DIR}")
+MESSAGE( STATUS "OSGUTIL_LIBRARY = ${OSGUTIL_LIBRARY}")
+################################################## BUILD THE LIBRARY #######################################
+SET(LIB_NAME ossimPlanet)
+
+INCLUDE_DIRECTORIES(${${PROJECT_NAME}_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${OSSIM_INCLUDE_DIR})
+
+IF(OSSIMPREDATOR_FOUND AND BUILD_OSSIMPREDATOR)
+ INCLUDE_DIRECTORIES(${OSSIMPREDATOR_INCLUDE_DIR})
+ ADD_DEFINITIONS("-DOSSIMPLANET_ENABLE_PREDATOR")
+ INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS})
+ELSE(OSSIMPREDATOR_FOUND AND BUILD_OSSIMPREDATOR)
+ MESSAGE(STATUS "Disabling Predator support in Planet")
+ SET(OSSIMPREDATOR_LIBRARY "")
+ SET(OSSIMPREDATOR_LIBRARIES "")
+ SET(OSSIMPREDATOR_INCLUDE_DIR "")
+ SET(FFMPEG_LIBRARIES "")
+ SET(FFMPEG_LIBRARY "")
+ENDIF(OSSIMPREDATOR_FOUND AND BUILD_OSSIMPREDATOR)
+
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${WMS_INCLUDE_DIR})
+
+IF(GPSTK_FOUND AND OSSIMPLANET_ENABLE_EPHEMERIS)
+ MESSAGE(STATUS "GPSTK_LIBRARY = ${GPSTK_LIBRARY}")
+ MESSAGE(STATUS "GPSTK_INCLUDE_DIR = ${GPSTK_INCLUDE_DIR}")
+ ADD_DEFINITIONS("-DOSSIMPLANET_ENABLE_EPHEMERIS")
+ INCLUDE_DIRECTORIES(${GPSTK_INCLUDE_DIR})
+ IF(REGEX_FOUND)
+ INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR})
+ MESSAGE(STATUS "REGEX_INCLUDE_DIR = ${REGEX_INCLUDE_DIR}")
+ MESSAGE(STATUS "REGEX_LIBRARIES = ${REGEX_LIBRARIES}")
+ ELSE()
+ set(REGEX_LIBRARIES "")
+ ENDIF()
+ELSE(GPSTK_FOUND AND OSSIMPLANET_ENABLE_EPHEMERIS)
+ SET(GPSTK_LIBRARY "")
+ENDIF(GPSTK_FOUND AND OSSIMPLANET_ENABLE_EPHEMERIS)
+
+
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR})
+
+
+FILE(GLOB OSSIMPLANET_SRCS RELATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/src/ossimPlanet/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/ossimPlanet/*.c")
+FILE(GLOB OSSIMPLANET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/ossimPlanet/*.h")
+
+IF(NOT BUILD_OSSIMPREDATOR)
+ LIST(REMOVE_ITEM OSSIMPLANET_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/ossimPlanet/ossimPlanetPredatorVideoLayerNode.cpp")
+ LIST(REMOVE_ITEM OSSIMPLANET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/ossimPlanet/ossimPlanetPredatorVideoLayerNode.h")
+ENDIF()
+
+IF(NOT WIN32)
+ LIST(REMOVE_ITEM OSSIMPLANET_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/ossimPlanet/iowin32.c")
+ELSE(NOT WIN32)
+ LIST(APPEND ${LIB_NAME}_EXTRA_LIBS "ws2_32" "winmm")
+ENDIF(NOT WIN32)
+
+SET(INSTALL_INCLUDE_DIR "include/ossimPlanet")
+OSSIM_LINK_LIBRARY(${LIB_NAME} COMPONENT_NAME ossim TYPE "${OSSIM_USER_DEFINED_DYNAMIC_OR_STATIC}" HEADERS ${OSSIMPLANET_HEADERS} SOURCE_FILES ${OSSIMPLANET_SRCS}
+ LIBRARIES ${OSSIM_LIBRARIES} ${OSGVIEWER_LIBRARY} ${OSGDB_LIBRARY} ${OSGGA_LIBRARY} ${OSGTEXT_LIBRARY} ${OSGUTIL_LIBRARY} ${OSG_LIBRARY} ${OPENTHREADS_LIBRARY} ${JPEG_LIBRARY} ${WMS_LIBRARY} ${GPSTK_LIBRARY} ${OSSIMPREDATOR_LIBRARY} ${ZLIB_LIBRARY} ${OPENGL_LIBRARIES} ${FFMPEG_LIBRARIES} ${REGEX_LIBRARIES}
+ INSTALL_LIB INSTALL_HEADERS VERSION_SYMLINKS ADDITIONAL_COMPILE_FLAGS "-DOSSIMPLANET_LIBRARY")
+
+
+############################################################# SETUP APPLICATIONS ##################################################
+set(TARGET_COMMON_LIBRARIES ossimPlanet ${OSSIMPREDATOR_LIBRARIES})
+FILE(GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/examples/ossimplanetviewer/*.cpp")
+OSSIM_SETUP_APPLICATION(ossimplanetviewer INSTALL COMMAND_LINE COMPONENT_NAME ossim SOURCE_FILES ${SOURCE_FILES})
+FILE(GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/examples/ossimplanettest/*.cpp")
+OSSIM_SETUP_APPLICATION(ossimplanettest INSTALL COMMAND_LINE COMPONENT_NAME ossim SOURCE_FILES ${SOURCE_FILES})
+IF(BUILD_OSSIMPREDATOR)
+ FILE(GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/examples/ossimplanetklv/*.cpp")
+ OSSIM_SETUP_APPLICATION(ossimplanetklv INSTALL COMMAND_LINE COMPONENT_NAME ossim SOURCE_FILES ${SOURCE_FILES})
+ENDIF()
+
+FILE(GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/apps/ossimplanet-chip/*.cpp")
+OSSIM_SETUP_APPLICATION(ossimplanet-chip INSTALL COMMAND_LINE COMPONENT_NAME ossim SOURCE_FILES ${SOURCE_FILES})
+
+####################################### SETUP THE UNINSTALL #################################
+OSSIM_ADD_COMMON_MAKE_UNINSTALL()
diff --git a/ossimPlanet/Doxyfile b/ossimPlanet/Doxyfile
new file mode 100644
index 0000000..2f95bb6
--- /dev/null
+++ b/ossimPlanet/Doxyfile
@@ -0,0 +1,1541 @@
+# Doxyfile 1.5.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = ossimPlanet
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = "Version 1.8.6"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = dox
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = /Users/dimitri/doxygen/mail/1.5.7/doxywizard/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = include src examples
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.vhd \
+ *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = .svn
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Options related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/ossimPlanet/GNUmakefile.old b/ossimPlanet/GNUmakefile.old
new file mode 100644
index 0000000..a55b01c
--- /dev/null
+++ b/ossimPlanet/GNUmakefile.old
@@ -0,0 +1,12 @@
+TOPDIR = .
+include $(TOPDIR)/Make/makedefs
+include $(TOPDIR)/Make/makedirdefs
+
+DIRS = $(TOP_LEVEL_DIRS)
+
+include $(TOPDIR)/Make/makedirrules
+include $(TOPDIR)/Make/versionrules
+include $(TOPDIR)/Make/instrules
+include $(TOPDIR)/Make/distrules
+include $(TOPDIR)/Make/helprules
+include $(TOPDIR)/Make/maketoprule
diff --git a/ossimPlanet/LICENSE.txt b/ossimPlanet/LICENSE.txt
new file mode 100644
index 0000000..c57eb30
--- /dev/null
+++ b/ossimPlanet/LICENSE.txt
@@ -0,0 +1,76 @@
+ libwms Public License, Version 0.0
+ ==========================================
+
+ Copyright (C) 2004 Garrett Potts.
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this licence document, but changing it is not allowed.
+
+ LIBWMS PUBLIC LICENCE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the libwms Public License (WMSGPL) version 0.0
+ or later.
+
+ Notes: the OSGPL is based on the LGPL, with the 4 exceptions laid in in
+ the wxWindows section below. The LGPL in the final section of this
+ license.
+
+
+-------------------------------------------------------------------------------
+
+ wxWindows Library Licence, Version 3
+ ====================================
+
+ Copyright (C) 1998 Julian Smart, Robert Roebling [, ...]
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this licence document, but changing it is not allowed.
+
+ WXWINDOWS LIBRARY LICENCE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public Licence as published by
+ the Free Software Foundation; either version 2 of the Licence, or (at
+ your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
+ General Public Licence for more details.
+
+ You should have received a copy of the GNU Library General Public Licence
+ along with this software, usually in a file named COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA.
+
+ EXCEPTION NOTICE
+
+ 1. As a special exception, the copyright holders of this library give
+ permission for additional uses of the text contained in this release of
+ the library as licenced under the wxWindows Library Licence, applying
+ either version 3 of the Licence, or (at your option) any later version of
+ the Licence as published by the copyright holders of version 3 of the
+ Licence document.
+
+ 2. The exception is that you may use, copy, link, modify and distribute
+ under the user's own terms, binary object code versions of works based
+ on the Library.
+
+ 3. If you copy code from files distributed under the terms of the GNU
+ General Public Licence or the GNU Library General Public Licence into a
+ copy of this library, as this licence permits, the exception does not
+ apply to the code that you add in this way. To avoid misleading anyone as
+ to the status of such modified files, you must delete this exception
+ notice from such code and/or adjust the licensing conditions notice
+ accordingly.
+
+ 4. If you write modifications of your own for this library, it is your
+ choice whether to permit this exception to apply to your modifications.
+ If you do not wish that, you must delete the exception notice from such
+ code and/or adjust the licensing conditions notice accordingly.
+
+
+------------------------------------------------------------------------------
diff --git a/ossimPlanet/Make/cygwin_plugin_def b/ossimPlanet/Make/cygwin_plugin_def
new file mode 100644
index 0000000..010d27c
--- /dev/null
+++ b/ossimPlanet/Make/cygwin_plugin_def
@@ -0,0 +1,15 @@
+
+#
+# blessed are those who try to make Windows behave like it should ...
+#
+
+ifeq ($(OS),CYGWIN)
+TARGET_BASENAME := $(PLUGIN_PREFIX)$(TARGET_BASENAME)
+PLUGIN_PREFIX := cyg
+endif
+
+ifeq ($(OS),MINGW)
+TARGET_BASENAME := $(PLUGIN_PREFIX)$(TARGET_BASENAME)
+PLUGIN_PREFIX := lib
+endif
+
diff --git a/ossimPlanet/Make/dependencies b/ossimPlanet/Make/dependencies
new file mode 100644
index 0000000..c9bb116
--- /dev/null
+++ b/ossimPlanet/Make/dependencies
@@ -0,0 +1,9 @@
+################################################################
+# Dependency library which have been installed on this system
+
+##########################################
+#
+# For any getCapabilities parsing expat must be installed
+# on your system.
+#
+EXPAT_INSTALLED = yes
diff --git a/ossimPlanet/Make/distrules b/ossimPlanet/Make/distrules
new file mode 100644
index 0000000..b47b959
--- /dev/null
+++ b/ossimPlanet/Make/distrules
@@ -0,0 +1,16 @@
+distribution :
+ @$(MAKEDIST) \
+ $(OS)\
+ $(TOPDIR)\
+ $(INST_LIBS)\
+ $(INST_INCLUDE)\
+ $(INST_EXAMPLES)\
+ $(INST_SRC)\
+ $(INST_EXAMPLE_SRC)\
+ "$(VERSION)-$(VERSION_REVISION)" \
+ $(INST_DOC)
+
+
+
+cleandist:
+ @$(MAKECLEANDIST)
diff --git a/ossimPlanet/Make/dolink.sh b/ossimPlanet/Make/dolink.sh
new file mode 100644
index 0000000..c071613
--- /dev/null
+++ b/ossimPlanet/Make/dolink.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+bye()
+{
+ echo $1
+ exit 1
+}
+
+TOPDIR=$1
+LNSRC=$2
+LNDEST=$3
+LINKCMD=$4
+
+## Check command line
+
+
+[ $# -lt 4 ] && bye "Usage: $0 <Top Directory> <Link Source> <Link Destination> <Link command>"
+
+## Check for existence of link source file
+[ -n "$LNSRC" ] || bye "Internal error (LNSRC definition)"
+
+## Check for existence of link destination file
+[ -n "$LNDEST" ] || bye "Internal error (LNDEST definition)"
+
+if diff -s $TOPDIR/$LNDEST $LNSRC >/dev/null 2>&1
+then
+ echo " =====> $LNSRC and $TOPDIR/$LNDEST are in sync"
+else
+ echo " =====> resetting $TOPDIR/$LNDEST to point to $LNSRC"
+
+ ## At this point, we must create a link at the link destination
+ ## which points back to our link source. This requires us to
+ ## build a path FROM the destination back to the source
+
+ #1) Get the source directory as an absolute path
+ SRCDIR=`pwd`/`dirname $LNSRC`
+
+ #2) Get the destination directory as an absolute path (TOPDIR is
+ ## a relative path from the current directory).
+ cd $TOPDIR
+ ROOTDIR=`pwd`
+ DESTDIR=`dirname "$ROOTDIR"/"$LNDEST"`
+
+ #3) Build a ../../ chain from the destination directory to the
+ ## current directory (ROOTDIR), which will become the prefix to
+ ## the path
+ T=`dirname $LNDEST`
+ while [ "$T" != "." ]
+ do
+ T=`dirname $T`;PFX=../"$PFX"
+ done
+
+ #4) strip the absolute path prefix of SRCDIR leading to the current
+ ## directory, so we are left with the relative path from the current
+ ## directory to the link source directory. Prefix that with PFX.
+ LINK="$PFX"`echo $SRCDIR $ROOTDIR | awk '{ print substr($1,length($2)+2,512) }'`/`basename $LNDEST`
+
+ #5) Create the links by changing to the destination directory,
+ ## removing any old versions of the link and creating a new one
+ [ -d `dirname $LNDEST` ] || mkdir -p `dirname $LNDEST`
+ cd `dirname $LNDEST`
+ rm -f `basename $LNDEST`
+ $LINKCMD $LINK `basename $LNDEST`
+fi
+
+exit 0
diff --git a/ossimPlanet/Make/help.sh b/ossimPlanet/Make/help.sh
new file mode 100755
index 0000000..9a35cfa
--- /dev/null
+++ b/ossimPlanet/Make/help.sh
@@ -0,0 +1,155 @@
+#!/bin/sh
+
+OS=$1
+TOPDIR=$2
+INST_LIBS=$3
+INST_PLUGINS=$4
+INST_INCLUDE=$5
+INST_EXAMPLES=$6
+INST_EXAMPLE_SRC=$7
+INST_DOC=$8
+INST_DATA=$9
+
+
+cat <<- EOF
+
+The following targets can be used with any subsystem as well as the top
+level build (build in the libwms Root directory). Note that debug versions
+and optimized version of targets reside in parallel.
+
+ make - Same as 'make opt'
+ make opt - Makes optimized versions of all targets
+ make debug - Makes debug versions of all targets.
+ make clean - Removes all object files (both optimized and debug
+ versions) and Makedepend files.
+ make cleanopt - Removes optimized version of object files and
+ Makedepend files.
+ make cleandbg - Removes debug version of object files and Makedepend
+ files.
+ make cleandepend - Removes Makedepend file(s) (both optimized and debug
+ versions)
+ make cleandependopt - Removes optimized version Makedepend file(s)
+ make cleandependdbg - Removes debug version Makedepend file(s)
+ make cleantarget - Removes only targets but leaves object files (both
+ optimized and debug versions)
+ make cleantargetopt - Removes only optimized targets but leaves optimized
+ objects files.
+ make cleantargetdbg - Removes only debug targets but leaves debug object
+ files
+ make clobber - Removes object files and targets (both optimized and
+ debug versions)
+ make clobberopt - Removes optimized object files and targets
+ make clobberdbg - Removes debug object files and targets
+ make beautify - Pretty print C++ files
+ make docs - Builds documentation database for current target
+ make depend - Force a rebuild of the dependency file. Note that
+ dependency files are generated automatically during
+ builds.
+
+
+Solaris, IRIX and Linux (some compilers) can build 64 bit targets. These
+require the ARCH=64 argument. For example:
+
+ make ARCH=64 - Same as 'make ARCH=64 opt'
+ make ARCH=64 opt - Builds 64 bit optimized targets
+ make ARCH=64 debug - Builds 64 bit debug versions of targets
+ make ARCH=64 clean - Removes all 64 bit object files (both optimized and
+ debug versions).
+
+ etc.
+
+The following targets may only be issued from the top-level libwms build:
+
+ make install - Install both execution environment and development
+ targets
+ make instbin - Install execution environment targets only. These
+ consist of libraries, plugins and example programs.
+ Libraries are installed in
+ o $INST_LIBS,
+ plugins are installed in
+ o $INST_PLUGINS,
+ and examples are installed in
+ o $INST_EXAMPLES
+ on $OS
+
+ make instdev - Install development targets only. These consist of
+ header files, source code to the example programs, and
+ documentation.
+ Header files are install in
+ o $INST_INCLUDE,
+ example source code is installed in
+ o $INST_EXAMPLE_SRC,
+ and documentation is installed in
+ o $INST_DOC
+ on $OS
+
+ make instlinks - Installs symbolic links at install locations for both
+ execution environment and development targets rather
+ than copyied files. Installing links is ideal for a
+ development environment for avoiding confusion about
+ which binaries are being run or linked to.
+
+ make instlinksbin - Installs symbolic links at install locations for
+ execution environment targets only.
+ make instlinksdev - Installs symbolic links at install locations for
+ development targets only
+ make instclean - Removes installed targets (files or links) from
+ installation locations for both execution environment
+ and development targets
+ make instcleanbin - Removes installed targets from installation locations
+ for execution environment targets only
+ make instcleandev - Removes installed targets from installation locations
+ for defelopment targets only
+
+Note that the following variables can be used to directly override the default
+installation locations for $OS.
+
+ make INST_LIBS=<libs_location> \\
+ INST_PLUGINS=<plugins_location>\\
+ INST_INCLUDE=<header_file_location>\\
+ INST_EXAMPLES=<examples_location>\\
+ INST_EXAMPLE_SRC=<example_src_location>\\
+ INST_DOC=<doc_location>\\
+ install
+
+ - Installs libraries in <libs_location>, plugins in
+ <plugins_location>, header files in
+ <header_file_location>, examples in <examples_location>,
+ example source code in <example_src_location> and
+ documentation in <doc_location>
+
+Note also that INST_LIBS, INST_PLUGINS, INST_INCLUDE, and INST_SHARE share
+a common prefix by default: INST_LOCATION. Further INST_EXAMPLES, INST_EXAMPLE_SRC,
+INST_DOC, and INST_DATA share a common prefix by default : INST_SHARE, which
+is located under INST_LOCATION by default. This provides a short cut for the
+above 'make' usage. For example,
+
+ make INST_LOCATION=/usr/local/libwms \\
+ INST_SHARE=/usr/share/libwms \\
+ install
+
+
+These values can be tested by reissuing 'make help' with these arguments.
+
+After doing a 'make install' or 'make instlinks', and if not already added,
+add
+
+ $INST_EXAMPLES
+
+to your PATH environmental variable to run the examples. If it is not already
+present, add
+
+ $INST_LIBS
+
+and
+
+ $INST_PLUGINS
+
+to your LD_LIBRARY_PATH environmental variable. When compiling programs
+using libwms headers add to your -I compile flags:
+
+ $INST_INCLUDE
+
+EOF
+
+exit 0
diff --git a/ossimPlanet/Make/helprules b/ossimPlanet/Make/helprules
new file mode 100644
index 0000000..42b210c
--- /dev/null
+++ b/ossimPlanet/Make/helprules
@@ -0,0 +1,11 @@
+help:
+ @$(TOPDIR)/Make/help.sh\
+ $(OS)\
+ $(TOPDIR)\
+ $(INST_LIBS)\
+ $(INST_PLUGINS)\
+ $(INST_INCLUDE)\
+ $(INST_DEMOS)\
+ $(INST_DEMO_SRC)\
+ $(INST_DOC)\
+ $(INST_DATA) | more
diff --git a/ossimPlanet/Make/instexamplesrc b/ossimPlanet/Make/instexamplesrc
new file mode 100755
index 0000000..6c6ad05
--- /dev/null
+++ b/ossimPlanet/Make/instexamplesrc
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+TOPDIR=$1
+INST_LIBS=$2
+INST_INCLUDE=$3
+INST_SRC=$4
+INST_EXAMPLE_SRC=$5
+INSTALLCMD=$6
+COMPILER=$7
+OPTF=$8
+shift; shift; shift; shift; shift; shift; shift; shift;
+DEPARG=$1
+LINKARGS=$2
+shift; shift;
+OTHER_LIBS=$1
+MAKE=$2
+
+copy_example_source()
+{
+ for d in `ls $TOPDIR/examples/ | grep -v CVS`
+ do
+ if [ -d $TOPDIR/examples/$d ]
+ then
+ THISDIR=`pwd`
+ cd $TOPDIR/examples/$d
+ [ -d "$INST_EXAMPLE_SRC/$d" ] || mkdir -m 0755 -p $INST_EXAMPLE_SRC/$d
+ echo " installing $d"
+ for f in `$MAKE __instfiles`
+ do
+ src=`echo $f | cut -f1 -d"="`
+ dst=`echo $f | cut -f2 -d"="`
+ if [ -z "$dst" ] ; then dst=$src; fi
+ if [ -f "$src" ] ; then
+ ###echo $INSTALLCMD `pwd`/$src $INST_EXAMPLE_SRC/$d/$dst
+ $INSTALLCMD `pwd`/$src $INST_EXAMPLE_SRC/$d/$dst ;
+ fi
+ done
+ cd $THISDIR
+ fi
+ done
+}
+
+generate_makedefs()
+{
+ cat <<-EOF
+
+TOPDIR ?= ../
+THISDIR = .
+INC = -I$INST_INCLUDE -I./
+DEF = $DEF
+CXXFLAGS = \$(ARCHARGS) $OPTF \$(DEF) \$(INC)
+LDFLAGS = \$(ARCHARGS) $OPTF -L$INST_LIBS $LINKARGS
+OBJS = \$(C++FILES:.cpp=.o) \$(CXXFILES:.cpp=.o) \$(CFILES:.c=.o)
+C++ = $COMPILER
+OTHER_LIBS = $OTHER_LIBS
+VPATH = ..
+
+EOF
+}
+
+
+
+generate_makerules()
+{
+ cat <<-EOF1 | sed 's/TAB/ /'
+
+all : \$(EXEC) \$(LIB) \$(PLUGIN)
+
+\$(EXEC) : Makedepend \$(OBJS)
+TAB\$(C++) \$(LDFLAGS) \$(OBJS) \$(LIBS) -o \$@
+
+\$(LIB) \$(PLUGIN) : \$(OBJS)
+TAB\$(C++) \$(LDFLAGS) \$(SHARED) \$(OBJS) \$(LIBS) -o \$@
+
+clean :
+TABrm -f \$(OBJS) \$(MAKEDEPEND)
+
+clobber : clean
+TABrm -f \$(EXEC) \$(LIB) \$(PLUGIN)
+
+
+Makedepend : \$(CXXFILES) \$(CFILES)
+TAB\$(C++) \$(INC) $DEPARG \$? > \$@
+
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+TAB\$(C++) \$(CXXFLAGS) -c $<
+
+sinclude Makedepend
+
+EOF1
+}
+
+
+[ -d $INST_SRC/Make ] || mkdir -m 0755 -p $INST_SRC/Make
+
+echo =========== Installing Example Source Code =================
+
+echo " generating make files ..."
+generate_makedefs > $INST_SRC/Make/makedefs
+generate_makerules > $INST_SRC/Make/makerules
+
+echo " copying example files ..."
+copy_example_source
+
+exit 0
diff --git a/ossimPlanet/Make/instrules b/ossimPlanet/Make/instrules
new file mode 100644
index 0000000..bbbdb90
--- /dev/null
+++ b/ossimPlanet/Make/instrules
@@ -0,0 +1,149 @@
+install :
+ @rm -f $(INSTLOGFILE)
+ @$(MAKE) __instbin __instdev
+ @cat $(INSTLOGFILE)
+
+instbin instdev :
+ @$(MAKE) __$@
+
+__instbin:
+ @$(MAKE) INSTSRC=$(TOPDIR)/bin/$(OS)$(ARCH) INSTDEST=$(INST_EXAMPLES) \
+ INSTALL?="$(INSTBINCMD)" __install
+ @$(MAKE) INSTSRC=$(TOPDIR)/lib/$(OS)$(ARCH) INSTDEST=$(INST_LIBS) \
+ INSTALL?="$(INSTBINCMD)" __install
+ @echo >> $(INSTLOGFILE)
+ @echo " Run-time environment installation successful. Add " \
+ >> $(INSTLOGFILE)
+ @echo " $(INST_EXAMPLES)" \
+ >> $(INSTLOGFILE)
+ @echo " to your PATH environmental variable, and" \
+ >> $(INSTLOGFILE)
+ @echo " $(INST_LIBS) and $(INST_PLUGINS)" \
+ >> $(INSTLOGFILE)
+ @echo " to your LD_LIBRARY_PATH if not already present." \
+ >> $(INSTLOGFILE)
+ @echo >> $(INSTLOGFILE)
+
+
+__instdev:
+ @for d in `ls -1 $(TOPDIR)/include/ | grep -v CVS`; \
+ do \
+ if [ -d $(TOPDIR)/include/$$d ]; \
+ then \
+ $(MAKE) INSTSRC=$(TOPDIR)/include/$$d INSTDEST=$(INST_INCLUDE)/$$d \
+ INSTALL?="$(INSTDEVCMD)" __install; \
+ fi \
+ done
+ @$(TOPDIR)/Make/instexamplesrc \
+ $(TOPDIR) \
+ $(INST_LIBS) \
+ $(INST_INCLUDE) \
+ $(INST_SRC) \
+ $(INST_EXAMPLE_SRC) \
+ "$(INSTDEVCMD)" \
+ "$(C++)" \
+ "$(OPTF)" \
+ "$(DEPARG)" \
+ "$(LINKARGS)" \
+ "$(OTHER_LIBS)" \
+ $(MAKE) \
+
+
+ @echo \
+ >> $(INSTLOGFILE)
+ @echo " Development environment installation successful. Add" \
+ >> $(INSTLOGFILE)
+ @echo " -I$(INST_INCLUDE)" \
+ >> $(INSTLOGFILE)
+ @echo " compile flag when compiling with libwms header files." \
+ >> $(INSTLOGFILE)
+ @echo " Example programs can be found at $(INST_EXAMPLE_SRC)." \
+ >> $(INSTLOGFILE)
+ @echo >> $(INSTLOGFILE)
+
+instlinks :
+ @rm -f $(INSTLOGFILE)
+ $(MAKE) INSTBINCMD="$(INSTLINKBINCMD)" __instbin
+ $(MAKE) INSTDEVCMD="$(INSTLINKDEVCMD)" __instdev
+ @cat $(INSTLOGFILE)
+
+instlinksbin :
+ @rm -f $(INSTLOGFILE)
+ $(MAKE) INSTBINCMD="$(INSTLINKBINCMD)" __instbin
+ @cat $(INSTLOGFILE)
+
+instlinksdev :
+ @rm -f $(INSTLOGFILE)
+ @$(MAKE) INSTDEVCMD="$(INSTLINKDEVCMD)" __instdev
+ @cat $(INSTLOGFILE)
+
+
+instclean : instcleanbin instcleandev
+
+instcleanbin :
+ @$(MAKE) INSTSRC=$(TOPDIR)/bin/$(OS)$(ARCH) INSTDEST=$(INST_EXAMPLES) \
+ INSTALL?="$(INSTBINCMD)" __instclean
+ @$(MAKE) INSTSRC=$(TOPDIR)/lib/$(OS)$(ARCH) INSTDEST=$(INST_LIBS) \
+ INSTALL?="$(INSTBINCMD)" __instclean
+
+instcleandev :
+ @for d in `ls -1 $(TOPDIR)/include/ | grep -v CVS`; \
+ do \
+ if [ -d $(TOPDIR)/include/$$d ]; \
+ then \
+ $(MAKE) INSTSRC=$(TOPDIR)/include/$$d INSTDEST=$(INST_INCLUDE)/$$d \
+ INSTALL?="$(INSTDEVCMD)" __instclean; \
+ fi \
+ done
+ @for d in `ls -1 $(TOPDIR)/examples | grep -v CVS`; \
+ do \
+ if [ -d $(TOPDIR)/examples/$$d ]; \
+ then \
+ $(MAKE) INSTSRC=$(TOPDIR)/examples/$$d INSTDEST=$(INST_EXAMPLE_SRC)/$$d \
+ INSTALL?="$(INSTDEVCMD)" __instclean; \
+ fi \
+ done
+
+__install :
+ @[ -n "$(INSTSRC)" ] || echo "Internal error (INSTSRC definition)"
+ @[ -n "$(INSTSRC)" ] && echo > /dev/null
+ @[ -n "$(INSTDEST)" ] || echo "Internal error (INSTDEST) definition)"
+ @[ -n "$(INSTDEST)" ] && echo > /dev/null
+ @[ -d $(INSTDEST) ] || mkdir -p $(INSTDEST)
+ @cd $(INSTSRC); \
+ THISDIR=`pwd`; \
+ if [ -n "`ls -1 | grep -v CVS`" ]; then \
+ for f in `ls -1 | grep -v CVS`; \
+ do \
+ if [ -f $$f ] ; \
+ then \
+ INSTPATH=$$THISDIR/$$f; \
+ $(INSTALL) $$INSTPATH $(INSTDEST)/$$f; \
+ fi \
+ done \
+ fi
+
+__instclean :
+ @[ -n "$(INSTSRC)" ] || echo "Internal error (INSTSRC definition)"
+ @[ -n "$(INSTSRC)" ] && echo > /dev/null
+ @[ -n "$(INSTDEST)" ] || echo "Internal error (INSTDEST definition)"
+ @[ -n "$(INSTDEST)" ] && echo > /dev/null
+ @if [ -d $(INSTDEST) ] ; \
+ then \
+ cd $(INSTSRC); \
+ if [ -n "`ls -1 | grep -v CVS`" ]; then \
+ for f in `ls -1 | grep -v CVS`; \
+ do \
+ if [ -f $$f ] ; \
+ then \
+ echo "rm -f $(INSTDEST)/$$f"; \
+ rm -f $(INSTDEST)/$$f; \
+ fi \
+ done \
+ fi; \
+ empty=`ls $(INSTDEST)`; \
+ if [ -z "$$empty" ]; \
+ then \
+ rm -rf $(INSTDEST); \
+ fi \
+ fi
diff --git a/ossimPlanet/Make/makedefs b/ossimPlanet/Make/makedefs
new file mode 100644
index 0000000..9e8448c
--- /dev/null
+++ b/ossimPlanet/Make/makedefs
@@ -0,0 +1,597 @@
+SHELL = /bin/sh
+OS := $(shell uname)
+
+include $(TOPDIR)/Make/dependencies
+
+## We don't care about architectural distinguishers in the OS
+## such as IRIX64, IRIX32, etc. so we truncate IRIX?? to IRIX
+ifeq ($(findstring IRIX,$(OS)),IRIX)
+OS := IRIX
+endif
+
+## Make CYGWIN_XXXX CYGWIN so it's "Windows cross platform" :)
+ifeq ($(findstring CYGWIN,$(OS)),CYGWIN)
+OS := CYGWIN
+#OS := MINGW
+endif
+
+# uncomment if you want allocation counting turned on.
+# Used for debugging memory leaks.
+#
+# DEF += -DOSGPLANET_ENABLE_ALLOCATION_COUNT
+# Enable Predator video (uncomment the next line)
+ifneq ("$(ENABLE_PREDATOR)","no")
+DEF += -DOSSIMPLANET_ENABLE_PREDATOR -DOSSIMPLANET_ENABLE_EPHEMERIS
+endif
+
+
+## Make MINGW_XXXX MINGW so it's "Windows cross platform" :)
+ifeq ($(findstring MINGW,$(OS)),MINGW)
+OS := MINGW
+endif
+
+# TOPDIR needs to be redefined for every GNUmakefile
+TOPDIR ?= ../
+THISDIR = .
+MAKEDEPEND = ignore
+
+#######################################################################
+##
+## VERSIONING SEMANTICS
+##
+## Version consistes of <major> . <minor> . <release> - <revision>
+## Where:
+## major : Production (0 = pre-production)
+## minor : 0-7 = Production minor, 8 = Alpha, 9 = Beta
+## release : Release tag
+## revision: Release revision - 0 = development (cutting edge).
+##
+## Usage:
+## Default - VERSION_REVISION is set to the value defined here
+## Env variable OSGPLANET_VERSION_REVISION overrides default
+## e.g.:
+## % setenv OSGPLANET_VERSION_REVISION 5
+## % make version
+## Command line overrides env variable
+## % make VERSION_REVISION=
+#######################################################################
+VERSION_MAJOR = 1
+VERSION_MINOR = 0
+VERSION_RELEASE = 0
+VERSION_REVISION ?= 0
+VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
+
+INC = -I$(TOPDIR)/include
+
+############################################################################
+## NOTE - Semantics for the use of ARCH, ARCHARGS, and ARCHINST parameters
+## ARCH - must be defined if the OS supports both 64 and 32 bit
+## architectures may remain undefined if it does not.
+## ARCHARGS - Compiler directives to indicate for which architecture
+## to build for
+## ARCHINST - Installation target directory. Define if the OS supports
+## more than one architecture (32 and 64).
+## for ARCH=32 - define ARCHINST only if the system uses an
+## extension on 'lib' to indicate 32 bit. e.g.
+## IRIX defines /usr/lib32
+## for ARCH=64 - Always define ARCHINST. Even if the OS
+## doesn't make a distinction, we will.
+############################################################################
+
+CXXFLAGS = $(ARCHARGS) $(DOF) $(DEF) $(INC)
+LDFLAGS = $(ARCHARGS) $(DOF) $(LINKARGS) -L$(TOPDIR)/lib/$(OS)$(ARCH)
+OBJS = $(C++FILES:.cpp=.o) \
+ $(CXXFILES:.cpp=.o) \
+ $(CFILES:.c=.o) \
+
+EXE_EXT =
+
+DOF = $(OPTF)
+DEBUGDIR = $(OS)$(ARCH).Debug
+OPTDIR = $(OS)$(ARCH).Opt
+BININST = bin
+LIBINST = lib
+
+
+ifeq ("$(INST_LOCATION)","")
+INST_LOCATION = /usr/local
+endif
+#INST_LOCATION = /Users/Shared/Development/package/ossimPlanetInstall
+INST_LIBS = $(INST_LOCATION)/lib$(ARCHINST)
+INST_INCLUDE = $(INST_LOCATION)/include
+INST_SHARE = $(INST_LOCATION)/share
+INST_EXAMPLES = $(INST_SHARE)/libossimplanet/bin
+INST_SRC = $(INST_SHARE)/libossimplanet/src
+INST_EXAMPLE_SRC = $(INST_SRC)/examples
+INST_DOC = $(INST_SHARE)/libossimplanet/doc
+INST_DATA = $(INST_SHARE)/libossimplanet/data
+LINK = ln -sf
+INSTBINCMD = install -m 755
+INSTDEVCMD = install -m 644
+INSTLINKBINCMD = $(LINK)
+INSTLINKDEVCMD = $(LINK)
+LIB_PREFIX = lib
+LIB_EXT = so
+PLUGIN_EXT = so
+MAKEDIST = echo " === Distribution build is not implemented yet for $(OS)"; printf "\n"
+INSTLOGFILE = /tmp/.ossimplanet_inst_log
+
+ifneq ("$(LIBWMS_INC_DIR)","")
+INC += -I$(LIBWMS_INC_DIR)
+endif
+
+ifneq ("$(LIBWMS_LIB_DIR)","")
+LDFLAGS += -L$(LIBWMS_LIB_DIR)
+endif
+
+ifneq ("$(OSSIMPREDATOR_INC_DIR)","")
+INC += -I$(OSSIMPREDATOR_INC_DIR)
+endif
+
+ifneq ("$(OSSIMPREDATOR_LIB_DIR)","")
+LDFLAGS += -L$(OSSIMPREDATOR_LIB_DIR) -lossimPredator
+endif
+
+ifneq ("$(OSSIM_INC_DIR)","")
+INC += -I$(OSSIM_INC_DIR)
+endif
+
+ifneq ("$(OSSIM_LIB_DIR)","")
+LDFLAGS += -L$(OSSIM_LIB_DIR)
+endif
+
+ifneq ("$(GPSTK_INC_DIR)","")
+INC += -I$(GPSTK_INC_DIR)
+endif
+
+ifneq ("$(GPSTK_LIB_DIR)","")
+LDFLAGS += -L$(GPSTK_LIB_DIR)
+endif
+
+ifneq ("$(OSSIM_LIB_DIR)","")
+LDFLAGS += -L$(OSSIM_LIB_DIR)
+endif
+
+ifneq ("$(OPENTHREADS_INC_DIR)","")
+INC += -I$(OPENTHREADS_INC_DIR)
+endif
+
+ifneq ("$(OPENTHREADS_LIB_DIR)","")
+LDFLAGS += -L$(OPENTHREADS_LIB_DIR)
+endif
+
+ifneq ("$(PRODUCER_INC_DIR)","")
+INC += -I$(PRODUCER_INC_DIR)
+endif
+
+ifneq ("$(PRODUCER_LIB_DIR)","")
+LDFLAGS += -L$(PRODUCER_LIB_DIR)
+endif
+
+ifneq ("$(OSG_INC_DIR)","")
+INC += -I$(OSG_INC_DIR)
+endif
+
+ifneq ("$(OSG_LIB_DIR)","")
+LDFLAGS += -L$(OSG_LIB_DIR)
+endif
+
+ifneq ("$(OSSIM_PREDATOR_LIB)","")
+LDFLAGS += -L$(OSSIM_PREDATOR_LIB)
+endif
+
+CC=gcc
+
+OSSIM_LIBS=
+OSG_LIBS = -L/usr/local/lib64 -L/usr/local/lib -L/usr/local/bin -losgViewer -losgText -losgGA -losgDB -losgUtil -losg -lOpenThreads -lossimPredator -lossim -ljpeg -lz -lgpstk
+
+RECURSIVE_TARGETS = \
+ opt\
+ debug\
+ clean\
+ cleandepend\
+ cleandependopt\
+ cleandependdbg\
+ cleandbg\
+ cleanopt\
+ cleantarget\
+ cleantargetopt\
+ cleantargetdbg\
+ clobber\
+ clobberdbg\
+ clobberopt\
+ cleantmp\
+ docs\
+ depend
+
+#### SUN OS Specific definitions
+ifeq ($(OS),SunOS)
+
+ #### if useing g++ on a sun
+ ifeq ($(COMPILER),gnu)
+ C++ = g++
+ DEPARG = -M
+ INC +=
+ DEF += -W -Wall -fPIC -fpermissive
+ OPTF = -O2
+ DBGF = -g
+ SHARED = -shared -fPIC
+ ARCH = 32
+ ifeq ($(ARCH),64)
+ ARCHARGS = -m64 -DARCH64
+ ARCHINST = 64
+ else
+ ARCHARGS =
+ endif
+ OTHER_LIBS = -lexpat -lcurl
+
+ #### using forte compilers (default)
+ else
+ C++ = CC
+ DEPARG = -xM1
+ INC +=
+ DEF += -features=extensions -w
+ OPTF = -xO4
+ DBGF = -g
+ SHARED = -G
+ ARCH = 32
+ ifeq ($(ARCH),64)
+ ARCHARGS = -xarch=v9 -DARCH64
+ ARCHINST = 64
+ else
+ ARCHARGS =
+ ARCHINST =
+ endif
+ OTHER_LIBS = -lCstd -lexpat -lcurl
+ LINKARGS =
+ endif
+ DYNAMICLIBRARYLIB = -ldl
+ SOCKET_LIBS = -lsocket -lnsl
+ INSTBINCMD = cp
+ INSTDEVCMD = cp
+ INST_LOCATION = /opt/libossimPlanet
+ MAKEDIST = $(TOPDIR)/Make/makepkg
+ OTHER_LIBS = -lexpat -lcurl -lfreetype
+ PNG_LIBS = -lpng -lz
+ JPEG_LIBS = -ljpeg
+ GIF_LIBS = -lungif
+ TIFF_LIB = -ltiff -lz -ljpeg
+ FREETYPE_LIB = -lfreetype
+endif
+
+#### IRIX Specific definitions
+ifeq ($(OS),IRIX)
+ CXX = CC
+ ifeq ($(CXX),CC)
+ LINKARGS = -L${TOPDIR}/lib -LANG:std -OPT:Olimit=0
+ C++ = CC
+ DEPARG = -M
+ INC += -I${TOPDIR}/include -I/usr/freeware/include
+ DEF += -LANG:std -OPT:Olimit=0 \
+ -DEBUG:woff=1681 -DEBUG:woff=1682 -DEBUG:woff=3303\
+ -MDupdate $(MAKEDEPEND)
+ OPTF = -O2
+ DBGF = -g
+ SHARED = -shared
+ PFLIBS = \
+ -lpf3ds -lpfdem -lpfdted -lpfdwb -lpfdxf -lpfevt \
+ -lpfflt -lpfgds -lpfgfo -lpfim -lpflsa -lpflsb \
+ -lpfnff -lpfobj -lpfpegg -lpfpfb -lpfphd -lpfpts \
+ -lpfrot -lpfscale -lpfsgf -lpfsgo -lpfsphere -lpfsv \
+ -lpftri -lpfunc -lpfvct -lpfdu -lpfutil -lpf -all -limage
+ ARCH = 32
+ ifeq ($(ARCH),64)
+ ARCHARGS = -64 -DARCH64
+ ARCHINST = 64
+ LINKARGS += -L/usr/freeware/lib64
+ PF_XTRA_LIBS = -L/usr/lib64/libpfdb -rpath /usr/lib64/libpfdb \
+ $(PFLIBS)
+ else
+ ARCHARGS = -n32
+ ARCHINST = 32
+ LINKARGS += -L/usr/freeware/lib32
+ PF_XTRA_LIBS = -L/usr/lib32/libpfdb -rpath /usr/lib32/libpfdb \
+ $(PFLIBS)
+ endif
+ else
+ LIBS = -lstdc++
+ LINKARGS = -L${TOPDIR}/lib
+ C++ = g++
+ INC += -I${TOPDIR}/include -I/usr/freeware/include
+ DEF += -fPIC -W -Wno-unused
+ OPTF = -O2
+ DBGF = -g -gstabs+
+ SHARED = -shared
+ PFLIBS = \
+ -lpf3ds -lpfdem -lpfdted -lpfdwb -lpfdxf -lpfevt \
+ -lpfflt -lpfgds -lpfgfo -lpfim -lpflsa -lpflsb \
+ -lpfnff -lpfobj -lpfpegg -lpfpfb -lpfphd -lpfpts \
+ -lpfrot -lpfscale -lpfsgf -lpfsgo -lpfsphere -lpfsv \
+ -lpftri -lpfunc -lpfvct -lpfdu -lpfutil -lpf -all -limage
+ ARCH = 32
+ ifeq ($(ARCH),64)
+ ARCHARGS = -mabi=64 -mips4 -DARCH64
+ ARCHINST = 64
+ LINKARGS += -L/usr/freeware/lib64
+ PF_XTRA_LIBS = -L/usr/lib64/libpfdb -rpath /usr/lib64/libpfdb \
+ $(PFLIBS)
+ else
+ ARCHARGS = -mabi=n32 -mips4
+ ARCHINST = 32
+ LINKARGS += -L/usr/freeware/lib32
+ PF_XTRA_LIBS = -L/usr/lib32/libpfdb -rpath /usr/lib32/libpfdb \
+ $(PFLIBS)
+ endif
+ endif
+
+ DYNAMICLIBRARYLIB =
+ OTHER_LIBS = -lm -lexpat -lcurl -lfreetype
+ PNG_LIBS = -lpng -lz
+ JPEG_LIBS = -ljpeg
+ GIF_LIBS = -lungif
+ TIFF_LIB = -ltiff -lz -ljpeg
+ FREETYPE_LIB = -lfreetype
+ MAKEDIST = $(TOPDIR)/Make/makeirixdist
+endif
+
+#### Linux specific definitions
+
+ifeq ($(OS),Linux)
+
+ ifeq (x$(CXX),x)
+ C++ = g++
+ else
+ C++ = $(CXX)
+ endif
+
+ DEPARG = -M
+ INC +=
+
+ ifeq ($(COMPILER),intel)
+ C++ = ecc
+ LIBS = -lgcc_s
+ DEF += -KPIC
+ OPTF = -O2
+ DBGF = -g
+ ifeq ($(SYSARCH),ia64)
+ ARCHARGS =
+ ARCH = IA64
+ ARCHINST = IA64
+ else
+ ARCHARGS =
+ ARCH = 32
+ ARCHINST =
+ endif
+ else
+ LIBS = -lstdc++
+ DEF += -W -Wall -fPIC
+ OPTF = -O2
+ DBGF = -g -gstabs+
+ SYSARCH := $(shell arch)
+ ifeq ($(SYSARCH),x86_64)
+ ARCHARGS =
+ ARCH = 64
+ ARCHINST = 64
+ else
+ ARCHARGS =
+ ARCH = 32
+ ARCHINST =
+ endif
+ endif
+
+
+ SHARED = -shared
+ DYNAMICLIBRARYLIB = -ldl
+ PF_XTRA_LIBS = -L/usr/lib/libpfdb -Xlinker -rpath /usr/lib/libpfdb \
+ -lpfdu -lpfutil -lpf -lossimPredator
+ SOCKET_LIBS =
+ OTHER_LIBS = -lwms -lexpat -lcurl -lfreetype
+ PNG_LIBS = -lpng -lz
+ JPEG_LIBS = -ljpeg
+ GIF_LIBS = -lungif
+ TIFF_LIB = -ltiff -lz -ljpeg
+ FREETYPE_LIB = -lfreetype
+ MAKEDIST = $(TOPDIR)/Make/makerpms
+endif
+
+#### FreeBSD specific definitions
+ifeq ($(OS),FreeBSD)
+ C++ = g++
+ DEPARG = -MM
+ INC += -I/usr/local/include
+ DEF += -W -Wall
+ OPTF = -O2
+ DBGF = -g
+ SHARED = -shared
+ ARCH =
+ ARCHINST =
+ ARCHARGS =
+ LINKARGS = -L/usr/local/lib -rpath /usr/local/lib
+ DYNAMICLIBRARYLIB =
+ SOCKET_LIBS =
+ OTHER_LIBS = -lwms -lexpat -lcurl -lfreetype
+ PNG_LIBS = -lpng -lz
+ JPEG_LIBS = -ljpeg
+ GIF_LIBS = -lungif
+ TIFF_LIB = -ltiff -lz -ljpeg
+ FREETYPE_LIB = -lfreetype
+endif
+
+#### MacOS X specific definitions
+ifeq ($(OS),Darwin)
+ ifeq (x$(CXX),x)
+ C++ = g++
+ else
+ C++ = $(CXX)
+ endif
+ INC += -F/System/Library/Frameworks -I/opt/local/include
+ LDFLAGS += -F/System/Library/Frameworks -L/usr/X11R6/lib -L/opt/local/lib
+ DEF += -Wall -D__USE_OSX_AGL_IMPLEMENTATION__
+ OPTF = -O2
+ DBGF = -g
+ DEPARG = -M $(DEF)
+ SHARED = -dynamic
+ ARCH = 32
+ ARCHINST =
+ ARCHARGS =
+ LINKARGS =
+ DYNAMICLIBRARYLIB =
+ CARBON_LIB = -framework Carbon
+# OTHER_LIBS = -lm -lstdc++ -lwms -lexpat -lcurl -ljpeg -lOpenThreads -lossim -llammpi++ -lmpi -llam -llammpio -flat_namespace -undefined suppress -lfreetype -lpng12
+ OTHER_LIBS = -lm -lstdc++ -lwms -lexpat -lcurl -ljpeg -lOpenThreads -lossim -flat_namespace -undefined suppress -lfreetype -lpng12 -framework OpenGL
+ PNG_LIBS = -lpng -lz
+ JPEG_LIBS = -ljpeg
+ GIF_LIBS = -lungif
+ TIFF_LIB = -ltiff -lz -ljpeg
+ FREETYPE_LIB = -lfreetype
+ X_INC = -I/usr/X11R6/include
+ X_LIBS = -lX11
+ LIB_EXT = dylib
+ LIBVERSION = -current_version $(VERSION) \
+ -compatibility_version \
+ $(VERSION_MAJOR).$(VERSION_MINOR).0
+
+ ifeq ($(DARWIN_QUICKTIME),yes)
+ DEF += -DDARWIN_QUICKTIME
+ endif
+
+ QUICKTIME = -framework QuickTime $(CARBON_LIB)
+
+endif
+
+#### Cygwin specific definitions
+ifeq ($(OS),CYGWIN)
+ C++ = c++
+ DEPARG = -M
+ INC +=
+ DEF += -DWIN32 -W -Wall -DNOMINMAX -D_WIN32_IMPLEMENTATION
+ OPTF = -O2
+ DBGF = -g
+ SHARED = -shared\
+ -Wl,--out-implib,$(TOPDIR)/lib/$(OS)/lib$(TARGET_BASENAME).dll.a -Wl,--export-all-symbols
+
+ EXE_EXT =.exe
+ ARCH =
+ ARCHINST =
+ ARCHARGS =
+ LINKARGS = -W -Wall
+ DYNAMICLIBRARYLIB =
+ SOCKET_LIBS =
+ OTHER_LIBS = -lwms -lexpat `curl-config --libs` -lfreetype -ljpeg -lz -lOpenThreads
+ PNG_LIBS = -lpng -lz
+ JPEG_LIBS = -ljpeg
+ GIF_LIBS = -lungif
+ TIFF_LIB = -ltiff -lz -ljpeg
+ FREETYPE_LIB = -lfreetype
+
+ LIBINST = bin
+ PLUGININST = bin/$(OS)$(ARCH)
+
+ LIB_PREFIX = cyg
+ LIB_EXT = dll
+ PLUGIN_EXT = dll
+ LINK = cp -f
+ INST_LOCATION = /usr/local/libossimPlanet
+ INST_LIBS = $(INST_LOCATION)/bin
+ INST_PLUGINS = $(INST_LOCATION)/bin
+ INST_INCLUDE = $(INST_LOCATION)/include
+ INST_SHARE_PREFIX = /usr/local/libossimPlanet
+ INST_SRC = $(INST_SHARE_PREFIX)/src
+ INST_EXAMPLES = $(INST_SHARE_PREFIX)/bin
+ INST_EXAMPLE_SRC = $(INST_SHARE_PREFIX)/src/demos
+ INST_DOC = $(INST_SHARE_PREFIX)/doc
+ INST_DATA = $(INST_SHARE_PREFIX)/data
+ MAKEDIST = $(TOPDIR)/Make/makeinnosetup
+endif
+
+#### Mingw specific definitions
+ifeq ($(OS),MINGW)
+ C++ = c++ -mthreads
+ DEPARG = -M
+ INC += -I/usr/local/include -I/usr/local/include/ossim -I$(HOME)/ossim/src/packages/gdal/frmts/jpeg/libjpeg -I$(HOME)/ossim/src/packages/gdal/frmts/gtiff/libtiff
+ DEF += -DWIN32 -Wall -DOSSIMUSINGDLL
+# -W
+ OPTF = -O2
+ DBGF = -g
+ SHARED = -shared -mthreads \
+ -Wl,--out-implib,$(TOPDIR)/lib/$(OS)/lib$(TARGET_BASENAME).dll.a -Wl,--export-all-symbols
+
+ EXE_EXT =.exe
+ ARCH =
+ ARCHINST =
+ ARCHARGS =
+ LINKARGS = -W -Wall
+ DYNAMICLIBRARYLIB =
+ OTHER_LIBS = -L/usr/local/lib/ossim -L/usr/local/bin -L/usr/local/lib -lwms -lglu32 -lopengl32
+
+ LIBINST = bin
+ PLUGININST = bin/$(OS)$(ARCH)
+
+ LIB_PREFIX = lib
+ LIB_EXT = dll
+ PLUGIN_EXT = dll
+ LINK = cp -f
+ INST_LOCATION = /usr/local
+ INST_LIBS = $(INST_LOCATION)/bin
+ INST_PLUGINS = $(INST_LOCATION)/bin
+ INST_INCLUDE = $(INST_LOCATION)/include
+ INST_SHARE_PREFIX = /usr/local
+ INST_SRC = $(INST_SHARE_PREFIX)/src
+ INST_EXAMPLES = $(INST_SHARE_PREFIX)/bin
+ INST_EXAMPLE_SRC = $(INST_SHARE_PREFIX)/src/examples
+ INST_DOC = $(INST_SHARE_PREFIX)/doc
+ INST_DATA = $(INST_SHARE_PREFIX)/data
+ PNG_LIBS =
+ JPEG_LIBS =
+ GIF_LIBS =
+ TIFF_LIB =
+ FREETYPE_LIB = -lfreetype
+endif
+
+#### HP-UX Specific definitions
+# contributed by tino.schwarze at informatik.tu-chemnitz.de
+
+ifeq ($(OS),HP-UX)
+
+ C++ = g++
+ DEPARG = -M
+ INC +=
+ DEF += -W -Wall -fPIC
+ OPTF = -O2
+ # gcc 3.1 uses DWARF as default, my GDB might not yet support this...
+ # at least I've got problems everywhere
+ DBGF = -g -gstabs+
+ SHARED = -shared -fPIC
+ ARCH = 32
+ifeq ($(ARCH),64)
+ # not yet tested
+ ARCHARGS = -march=2.0 -DARCH64
+ ARCHINST = 64
+else
+ # at least my gcc 3.1 defaults to HP-PA RISC 1.1
+ ARCHARGS =
+ ARCHINST =
+endif
+ LINKARGS =
+ LIB_EXT = sl
+ PLUGIN_EXT = sl
+ DYNAMICLIBRARYLIB = -ldld
+ SOCKET_LIBS =
+ # make sure that global constructors/destructors are called upon
+ # shl_load() / shl_unload() - this is a gcc specific workaround
+ OTHER_LIBS = -lm -Wl,+init -Wl,_GLOBAL__DI -Wl,+fini -Wl,_GLOBAL__DD -lexpat -lcurl -lfreetype
+ FREETYPE_INCLUDE = -I/opt/freetype/include -I/opt/freetype/include/freetype2
+ FREETYPE_LIB = -L/opt/freetype/lib -lfreetype
+ PNG_INCLUDE = -I/opt/libpng/include
+ PNG_LIBS = -L/opt/libpng/lib -lpng -L/opt/zlib/lib -lz
+ JPEG_INCLUDE = -I/opt/jpeg-6/include
+ JPEG_LIBS = -L/opt/jpeg-6/lib -ljpeg
+ TIFF_INCLUDE = -I/opt/tiff-3.5/include
+ TIFF_LIB = -L/opt/tiff-3.5/lib -ltiff
+ GIF_INCLUDE = -I/opt/libungif/include
+ GIF_LIBS = -L/opt/libungif/lib -lungif
+
+endif
+
+VPATH=..
+
diff --git a/ossimPlanet/Make/makedirdefs b/ossimPlanet/Make/makedirdefs
new file mode 100644
index 0000000..61c2cb6
--- /dev/null
+++ b/ossimPlanet/Make/makedirdefs
@@ -0,0 +1,26 @@
+
+################################################################
+# Directories traversed from the top level
+TOP_LEVEL_DIRS = \
+ src \
+ examples
+
+
+################################################################
+# Directories traversed in the TOPDIR/src directory
+SRC_DIRS = ossimPlanet
+
+
+SRC_DIRS += \
+ ../examples
+
+################################################################
+# Directories traversed in the TOPDIR/src/osgPlugins directory
+
+PLUGIN_DIRS =
+
+
+EXAMPLE_DIRS = \
+ ossimplanetviewer \
+ ossimplanettest
+
diff --git a/ossimPlanet/Make/makedirrules b/ossimPlanet/Make/makedirrules
new file mode 100644
index 0000000..68056f5
--- /dev/null
+++ b/ossimPlanet/Make/makedirrules
@@ -0,0 +1,6 @@
+
+default : $(DIRS)
+ @for f in $(DIRS); do echo "Entering directory $$f"; cd $$f; $(MAKE) $@ || exit 1; cd ..; done
+
+$(RECURSIVE_TARGETS) : $(DIRS)
+ @for f in $(DIRS); do echo "Entering directory $$f"; cd $$f; $(MAKE) $@ || exit 1; cd ..; done
diff --git a/ossimPlanet/Make/makeinnosetup b/ossimPlanet/Make/makeinnosetup
new file mode 100755
index 0000000..88ab159
--- /dev/null
+++ b/ossimPlanet/Make/makeinnosetup
@@ -0,0 +1,152 @@
+#!/bin/sh
+
+VERSION=`make -s version`
+
+print_header()
+{
+ cat <<- EOF
+[Setup]
+AppName=Open Scene Graph
+AppVerName=Open Scene Graph $VERSION
+AppPublisher=OpenSceneGraph
+AppPublisherURL=http://www.openscenegraph.com
+AppSupportURL=http://www.openscenegraph.com
+AppUpdatesURL=http://www.openscenegraph.com
+DefaultDirName={pf}\OpenSceneGraph
+DisableDirPage=yes
+DefaultGroupName=OpenSceneGraph
+DisableProgramGroupPage=yes
+LicenseFile=LICENSE.txt
+EOF
+}
+
+# Usage:
+# do_dir $DIR
+#
+
+print_file_entry()
+{
+ DIR=$1
+ FILE=$2
+ printf "Source: \"%s\\\%s\"; DestDir: \"{app}\\\%s\\\"; Flags: ignoreversion\n"\
+ $DIR $FILE $DIR
+
+}
+
+do_dir()
+{
+ DIR=$1
+ shift;
+
+ DOS_DIR=`echo $DIR | sed 's/\\//\\\/g'`
+
+ if [ $# -gt 0 ]
+ then
+ while [ $# -gt 0 ]
+ do
+ match=$1
+ shift;
+ for f in `find $DIR -type f | \
+ grep -v CVS | \
+ grep osg |
+ grep "$match"`
+ do
+ print_file_entry $DOS_DIR `basename $f`
+ done
+ done
+ else
+ for f in `find $DIR -type f | grep -v CVS | grep osg`
+ do
+ print_file_entry $DOS_DIR `basename $f`
+ done
+
+ fi
+}
+
+print_files()
+{
+ echo "[Files]"
+
+ do_dir lib .lib
+ do_dir bin .exe .dll
+ for dir in `ls -1 include | grep osg | grep -v CVS`
+ do
+ do_dir include/"$dir"
+ done
+}
+
+print_script()
+{
+ print_header
+ print_files
+}
+
+BUILD_ISS=1
+BUILD_DISTRIBUTION=1
+CLEAN_UP=1
+
+while [ $# -gt 0 ]
+do
+ case $1 in
+ -c )
+ BUILD_ISS=0
+ BUILD_DISTRIBUTION=0
+ CLEAN_UP=1
+ ;;
+
+ -d )
+ BUILD_ISS=0
+ BUILD_DISTRIBUTION=1
+ CLEAN_UP=0
+ ;;
+
+ -n )
+ CLEAN_UP=0
+ ;;
+
+ -s )
+ BUILD_ISS=1
+ BUILD_DISTRIBUTION=0
+ CLEAN_UP=0
+ ;;
+ esac
+
+ shift;
+done
+
+if [ $BUILD_ISS = 1 ]
+then
+ echo Building Inno Setup script ....
+ rm -f osg.iss
+
+ print_script | awk '{ printf "%s\r\n", $0 }' > osg.iss
+fi
+
+if [ $BUILD_DISTRIBUTION = 1 ]
+then
+ echo Building distribution ...
+ OS=`uname | cut -b1-6`
+
+ if [ "$OS" = "CYGWIN" ]
+ then
+ C:/Program\ Files/Inno\ Setup\ 3/iscc.exe osg.iss
+ [ -d dist/Win32 ] || mkdir -p dist/Win32
+ mv Output/setup.exe dist/Win32/OpenSceneGraph_"$VERSION"_setup.exe
+ rm -rf Output
+ else
+ echo " Distribution may only be built under Cygwin with Inno Setup"
+ fi
+fi
+
+if [ $CLEAN_UP = 1 ]
+then
+ echo Cleaning up...
+ rm -f osg.iss
+fi
+
+
+
+
+
+
+
diff --git a/ossimPlanet/Make/makeirixdist b/ossimPlanet/Make/makeirixdist
new file mode 100755
index 0000000..5340687
--- /dev/null
+++ b/ossimPlanet/Make/makeirixdist
@@ -0,0 +1,158 @@
+#!/bin/sh
+
+echo_idb()
+{
+
+## EOE
+ #####################################################################
+ # Capture bin directory
+
+ dd=`echo $INST_EXAMPLES | sed -e 's/\///'`
+ echo d 0755 root sys $dd $dd osg.eoe.sw
+ cd bin
+ for f in `find . -type l -print | grep -v CVS | sed -e 's/\.\///' | grep -v "\."`
+ do
+ echo f 0755 root sys $dd/$f $dd/$f osg.eoe.sw
+ done
+ cd ..
+
+ #####################################################################
+ # Capture lib and lib/osgPlugins directory
+
+ dd=`echo $INST_LIBS | sed -e 's/\///'`
+ echo d 0755 root sys $dd $dd osg.eoe.sw
+ echo d 0755 root sys $dd/osgPlugins $dd/osgPlugins osg.eoe.sw
+ cd lib
+ for f in `find . -type l -print | grep -v CVS | sed -e 's/\.\///' `
+ do
+ echo f 0755 root sys $dd/$f $dd/$f osg.eoe.sw
+ done
+ cd ..
+
+## DEV
+ #####################################################################
+ # Capture include directories and files
+ dd=`echo $INST_INCLUDE | sed -e 's/\///'`
+
+ cd include
+
+ echo d 0755 root sys $dd $dd osg.dev.sw
+ for d in `find . -type d -print | grep -v CVS | sed -e 's/\.\///' | grep -v "\."`
+ do
+ echo d 0755 root sys $dd/$d $dd/$d osg.dev.sw
+ done
+ cd ..
+
+ #####################################################################
+ # Capture installed example source
+
+ dd=`echo $INST_SRC | sed -e 's/\///'`
+ THISDIR=`pwd`
+ cd $INST_SRC
+ for d in `find . -type d -print | sed -e 's/\.\///' | grep -v "\." `
+ do
+ echo d 0755 root sys $dd/$d $dd/$d osg.dev.sw
+ done
+ for f in `find . -type f -print | sed -e 's/\.\///'`
+ do
+ echo f 0755 root sys $dd/$f $dd/$f osg.dev.sw
+ done
+ cd $THISDIR
+}
+
+make_idb()
+{
+ echo_idb | sort -k5
+}
+
+make_spec()
+{
+ cat <<- SPEC_EOF
+product osg
+ id "Open Scene Graph `bin/osgversion`"
+ image eoe
+ id "Open Scene Graph `bin/osgversion` Run-Time Environment"
+ version `bin/osgversion`
+ order 9999
+ subsys sw default
+ id "Open Scene Graph `bin/osgversion` Run-Time Environment"
+ replaces self
+ exp osg.eoe.sw
+ endsubsys
+ endimage
+ image dev
+ id "Open Scene Graph `bin/osgversion` Development Environment"
+ version `bin/osgversion`
+ order 9999
+ subsys sw default
+ id "Open Scene Graph `bin/osgversion` Development Environment"
+ replaces self
+ exp osg.dev.sw
+ endsubsys
+ endimage
+endproduct
+SPEC_EOF
+}
+
+intro()
+{
+ echo; echo;
+ echo "============ Building the $OS Distribution Package ==================="
+ echo ""
+ echo " Please note that this script requires that"
+ echo
+ echo " 'make install' "
+ echo
+ echo " be previously run. Please run "
+ echo
+ echo " 'make distribution' "
+ echo
+ echo " with the same arguments (if any) as 'make install'"
+ echo
+ repeat=1
+ while [ $repeat = 1 ]
+ do
+ printf " Continue? (y/n) [y]: "
+ read resp
+ case $resp in
+ ""|Yes|YES|yes|Y|y) repeat=0 ;;
+ n|N|no|NO) return 1; repeat=0;;
+ *) repeat=1;;
+ esac
+ done
+
+ return 0
+}
+
+OS=$1
+TOPDIR=$2
+INST_LIBS=$3
+INST_PLUGINS=$4
+INST_INCLUDE=$5
+INST_EXAMPLES=$6
+INST_SRC=$7
+INST_EXAMPLE_SRC=$8
+shift;shift; shift;shift; shift;shift; shift;shift;
+INST_DOC=$1
+INST_DATA=$2
+
+
+intro || exit 0
+
+make_spec > dist/Irix/osg.spec
+make_idb > dist/Irix/osg.idb
+
+DIST_DIR=Distribution-`bin/osgversion`
+
+cd dist/Irix
+rm -rf $DIST_DIR
+mkdir $DIST_DIR
+/usr/sbin/gendist -sbase / -idb osg.idb -spec osg.spec -dist $DIST_DIR
+cd $DIST_DIR
+tar cvf ../osg.tardist *
+mv ../osg.tardist .
+cd ../../../
+
+
+
+exit 0
diff --git a/ossimPlanet/Make/makepkg b/ossimPlanet/Make/makepkg
new file mode 100755
index 0000000..3f9f3ed
--- /dev/null
+++ b/ossimPlanet/Make/makepkg
@@ -0,0 +1,220 @@
+#!/bin/sh
+
+
+die()
+{
+ echo >& $1
+ exit 1
+}
+
+x()
+{
+ echo $*
+ $*
+}
+
+
+
+print_pkginfo()
+{
+
+ __pstamp=`fgrep $LOGNAME /etc/passwd | cut -f5 -d":"`
+ cat <<- EOF
+PKG="$1"
+NAME="$2"
+`[ "$OS" = "SunOS" ] && echo ARCH=sparc`
+VERSION=`gmake -s version`
+CATEGORY="application,graphics,opengl"
+DESC="$3"
+BASEDIR="/opt/"
+VENDOR="OpenSceneGraph"
+EMAIL="info at openscenegraph.org"
+PSTAMP=$__pstamp
+URL="http://openscenegraph.org"
+MAXINST="1"
+EOF
+
+}
+
+print_prototype()
+{
+ echo "i pkginfo"
+ [ -f depend ] && echo "i depend"
+
+ for d in $*
+ do
+ d=`echo $d | sed 's/\/opt\///`
+ echo "d none $d ? root sys"
+ done
+
+ for d in $*
+ do
+ for f in `ls -1 $d`
+ do
+ f=$d/$f
+ if [ -f $f ]
+ then
+ [ -x $f ] && MODE=0555 || MODE=0444
+ dest=`echo $f | sed 's/\/opt\///'`
+ echo "f none $dest=$f $MODE root sys"
+ fi
+ done
+ done
+
+}
+
+make_installable()
+{
+ PKGNAME=$1
+ PKGDIR=$PKGNAME.pkg
+ DISTNAME="$PKGNAME"-"`gmake -s version`"-"$OS".shar
+
+ THISDIR=`pwd`
+ cd $PKGSUBDIR
+
+ cat << INSTALL_EOF > $DISTNAME
+
+#!/bin/sh
+cat <<- 'LEOF' | uudecode -p | gzip -d -c | tar xvf -
+`tar cvf - $PKGDIR | gzip | uuencode .tmpuu`
+LEOF
+
+/bin/sh << EOF
+echo =========== INSTALLING $DISTNAME =================
+pkgadd -d $PKGNAME.pkg $PKGNAME
+rm -rf $PKGDIR
+EOF
+
+
+INSTALL_EOF
+
+ chmod +x $DISTNAME
+ cd $THISDIR
+}
+
+
+make_package()
+{
+ PKGNAME=$1
+ PKGDIR=$PKGSUBDIR/$PKGNAME.pkg
+ x rm -rf $PKGDIR
+ x mkdir $PKGDIR
+
+ echo Making pkginfo ...
+ print_pkginfo "$1" "$2" "$3" > $PKGDIR/pkginfo
+
+ shift; shift; shift
+
+ echo Making prototype ...
+
+ print_prototype $* > $PKGDIR/prototype
+
+# DISTNAME="$PKGNAME"-"`$TOPDIR/bin/osgversion`"-"$OS"-"local"
+
+ THISDIR=`pwd`
+ x cd $PKGDIR
+ x pkgmk -d .
+ x cd $THISDIR
+# make_installable $PKGNAME $PKGDIR $DISTNAME
+# x pkgtrans -s $PKGDIR $DISTNAME $PKGNAME
+# x mv "$PKGDIR"/"$DISTNAME" "$PKGDIR"/..
+}
+
+
+intro()
+{
+ echo; echo;
+ echo "============ Building the $OS Distribution Package ==================="
+ echo ""
+ echo " Please note that this script requires that"
+ echo
+ echo " 'make install' "
+ echo
+ echo " be previously run. Please run "
+ echo
+ echo " 'make distribution' "
+ echo
+ echo " with the same arguments (if any) as 'make install'"
+ echo
+ repeat=1
+ while [ $repeat = 1 ]
+ do
+ printf " Continue? (y/n) [y]: "
+ read resp
+ case $resp in
+ ""|Yes|YES|yes|Y|y) repeat=0 ;;
+ n|N|no|NO) return 1; repeat=0;;
+ *) repeat=1;;
+ esac
+ done
+
+ return 0
+}
+
+intro || exit 0
+
+OS=$1
+TOPDIR=$2
+INST_LIBS=$3
+INST_PLUGINS=$4
+INST_INCLUDE=$5
+INST_EXAMPLES=$6
+INST_SRC=$7
+INST_EXAMPLE_SRC=$8
+shift;shift; shift;shift; shift;shift; shift;shift;
+INST_DOC=$1
+INST_DATA=$2
+
+
+PKGSUBDIR=dist/PKG
+
+make_package\
+ "OpenSceneGraph" \
+ "Open Scene Graph - Run-time environment"\
+ "An OpenGL based scene graph. This installation includes a set of run-time libraries, and example programs"\
+ $INST_LIBS $INST_PLUGINS $INST_EXAMPLES\
+
+make_installable "OpenSceneGraph"
+
+#
+# Capture include directories
+#
+SUBDIRS=`ls $TOPDIR/include | grep -v CVS`
+INSTARG=""
+for d in $SUBDIRS
+do
+ dd="$INST_INCLUDE"/"$d"
+ [ -d $dd ] && INSTARG="$INSTARG $dd"
+done
+
+#
+# Capthre examples subdirectories
+#
+SUBDIRS=`ls $TOPDIR/src/examples | grep -v CVS`
+for d in $SUBDIRS
+do
+ dd="$INST_EXAMPLE_SRC"/"$d"
+ [ -d $dd ] && INSTARG="$INSTARG $dd"
+done
+
+#
+# Capture Make subdirectory
+#
+dd="$INST_SRC"/"Make"
+
+echo dd is $dd
+ls $dd
+
+[ -d $dd ] && INSTARG="$INSTARG $dd"
+
+
+make_package\
+ "OpenSceneGraph-dev"\
+ "Open Scene Graph - Development environment"\
+ "An OpenGL based scene graph. This installation includes header files and example program source files"\
+ $INSTARG
+
+make_installable "OpenSceneGraph-dev"
+
+
+exit 0
diff --git a/ossimPlanet/Make/makerpms b/ossimPlanet/Make/makerpms
new file mode 100755
index 0000000..5764f76
--- /dev/null
+++ b/ossimPlanet/Make/makerpms
@@ -0,0 +1,200 @@
+#!/bin/sh
+
+die()
+{
+ echo $1
+ exit 1
+}
+
+
+s_install()
+{
+ src_DIR=$1
+ mode=$2
+ dst_DIR=$RPM_BUILD_DIR/`echo $3 | sed 's/\///'`
+
+ [ -d $dst_DIR ] || mkdir -p $dst_DIR
+
+ THISDIR=`pwd`
+ cd $src_DIR
+ for f in `ls -1`
+ do
+ if [ -f $f ]
+ then
+ install -m $mode $f $dst_DIR/$f
+ fi
+ done
+ cd $THISDIR
+}
+
+
+print_attr()
+{
+ dst_DIR=$1
+ mode=$2
+ t_dir=$RPM_BUILD_DIR/$dst_DIR
+
+ THISDIR=`pwd`
+ cd $t_dir
+ for f in `ls -1`
+ do
+ [ -f $f ] && echo "%attr($mode, root, root) $dst_DIR/$f"
+ done
+ cd $THISDIR
+}
+
+make_targz()
+{
+ THISDIR=`pwd`
+ src_dir=$1
+ cd $RPM_BUILD_DIR/..
+ tar cvf - $src_dir |\
+ gzip > /usr/src/redhat/SOURCES/$src_dir.tar.gz
+ cd $THISDIR
+}
+
+make_spec()
+{
+ name=$1
+ cat <<-LEOF > $TOPDIR/dist/RPM/$name.spec
+
+Summary: libwms - get and parse wms data
+Name: $name
+Version: $REV
+Release: $REL
+Copyright: LGPL
+Group: Graphics
+Source: $name-$REV.tar.gz
+URL: http://www.flids.com
+Packager: `awk -f - /etc/passwd <<-EOF
+BEGIN { FS=":"}
+{
+ if( \\$1 == "$LOGNAME" )
+ print \\$5
+}
+EOF`
+
+%description
+
+
+%prep
+
+%setup
+
+%build
+
+%install
+
+cd $RPM_BUILD_DIR
+tar cvf - . | tar xvfC - /
+
+# ---------------------
+# FILES Sections
+%files
+
+LEOF
+}
+
+
+make_wms()
+{
+ RPM_BUILD_DIR=/usr/src/redhat/BUILD/libwms-$REV
+ rm -rf $RPM_BUILD_DIR
+ mkdir $RPM_BUILD_DIR
+
+ s_install $TOPDIR/lib 755 $INST_LIBS
+ s_install $TOPDIR/bin 755 $INST_EXAMPLES
+
+ make_targz -$REV
+ make_spec libwms
+
+ print_attr $INST_LIBS 755 >> $TOPDIR/dist/RPM/libwms.spec
+ print_attr $INST_EXAMPLES 755 >> $TOPDIR/dist/RPM/libwms.spec
+
+ rpmbuild -bb --clean $TOPDIR/dist/RPM/libwms.spec
+
+ mv /usr/src/redhat/RPMS/i386/libwms-$REV-$REL.i386.rpm dist/RPM
+}
+
+make_wms_dev()
+{
+ RPM_BUILD_DIR=/usr/src/redhat/BUILD/libwms_dev-$REV
+ rm -rf $RPM_BUILD_DIR
+ mkdir $RPM_BUILD_DIR
+
+ for d in `ls $TOPDIR/include | grep -v CVS`
+ do
+ [ -d $TOPDIR/include/$d ] && \
+ s_install $TOPDIR/include/$d 644 $INST_INCLUDE/$d
+ done
+
+
+ for d in `ls -1 $INST_EXAMPLE_SRC`
+ do
+ if [ -d $INST_EXAMPLE_SRC/$d ]
+ then
+ s_install $INST_EXAMPLE_SRC/$d 644 $INST_EXAMPLE_SRC/$d
+ fi
+ cd $THISDIR
+ done
+
+ s_install $INST_SRC/Make 644 $INST_SRC/Make
+
+
+ make_targz libwms_dev-$REV
+ make_spec libwms_dev
+
+ for d in `ls -1 $RPM_BUILD_DIR/$INST_INCLUDE`
+ do
+ print_attr $INST_INCLUDE/$d 755 >> $TOPDIR/dist/RPM/libwms_dev.spec
+ done
+
+ for d in `ls -1 $RPM_BUILD_DIR/$INST_EXAMPLE_SRC`
+ do
+ print_attr $INST_EXAMPLE_SRC/$d 755 >> $TOPDIR/dist/RPM/libwms_dev.spec
+ done
+
+ print_attr $INST_SRC/Make 755 >> $TOPDIR/dist/RPM/libwms_dev.spec
+
+ rpm -ba --clean $TOPDIR/dist/RPM/libwms_dev.spec
+
+ mv /usr/src/redhat/RPMS/i386/libwms_dev-$REV-$REL.i386.rpm dist/RPM
+}
+
+if [ "`whoami`" != "root" ]
+then
+ echo
+ echo " === makerpm : You must be root do make the RPM distribution."
+ echo
+ exit 1
+fi
+
+if [ $# -ne 9 ]
+then
+ echo
+ echo makerpm : Internal Error - Bad Usage
+ echo
+ exit 1
+fi
+
+OS=$1
+TOPDIR=$2
+INST_LIBS=$3
+INST_INCLUDE=$4
+INST_EXAMPLES=$5
+INST_SRC=$6
+INST_EXAMPLE_SRC=$7
+VERSION=$8
+shift; shift;shift; shift;shift; shift;shift;shift;
+INST_DOC=$1
+
+REV=$VERSION
+REL=1
+
+make_wms
+
+make_wms_dev
+
+
+
+exit 0
diff --git a/ossimPlanet/Make/makerules b/ossimPlanet/Make/makerules
new file mode 100644
index 0000000..b3e32de
--- /dev/null
+++ b/ossimPlanet/Make/makerules
@@ -0,0 +1,199 @@
+
+default: opt
+
+opt: $(EXEC:=.opt)\
+ $(LIB:=.opt)\
+ $(PLUGIN:=.opt)
+
+debug: $(EXEC:=.dbg)\
+ $(LIB:=.dbg)\
+ $(PLUGIN:=.dbg)
+
+cleandepend: cleandependopt cleandependdbg
+
+cleandependopt:
+ @[ -d $(OPTDIR) ] && cd $(OPTDIR); rm -f Makedepend; rm -rf .depend
+
+cleandependdbg:
+ @[ -d $(DEBUGDIR) ] && cd $(DEBUGDIR); rm -f Makedepend; rm -rf .depend
+
+cleantarget: cleantargetopt cleantargetdbg
+
+cleantargetopt:
+ @[ -d $(OPTDIR) ] && cd $(OPTDIR); rm -f $(EXEC) $(LIB) $(PLUGIN)
+
+cleantargetdbg:
+ @[ -d $(DEBUGDIR) ] && cd $(DEBUGDIR); rm -f $(EXEC) $(LIB) $(PLUGIN)
+
+clean: cleanopt cleandbg cleantmp cleandepend
+
+cleanopt:
+ @[ -d $(OPTDIR) ] && cd $(OPTDIR); rm -f $(OBJS) Makedepend; rm -rf .depend
+
+cleandbg:
+ @[ -d $(DEBUGDIR) ] && cd $(DEBUGDIR); rm -f $(OBJS) Makedepend; rm -rf .depend
+
+clobber: clobberdbg clobberopt
+
+clobberopt:
+ rm -rf $(OPTDIR)
+
+clobberdbg:
+ rm -rf $(DEBUGDIR)
+
+cleanlib:
+ rm -rf $(TOPDIR)/lib/*
+
+cleanbin:
+ rm -rf $(TOPDIR)/bin/*
+
+cleandoc:
+ rm -rf $(TOPDIR)/doc/*
+
+cleantmp:
+ @for f in * ; do [ -d $$f ]||rm -f $$f~; done
+
+docs:
+ [ "$(TARGET_BASENAME)" != "" ] && \
+ mkdir -p $(TOPDIR)/doc/$(TARGET_BASENAME) && \
+ doc++ -d $(TOPDIR)/doc/doc++/$(TARGET_BASENAME) -H -A \
+ $(TOPDIR)/include/$(TARGET_BASENAME)/* && \
+ echo "$(TARGET_BASENAME) HTML documentation created in "\
+ "$(TOPDIR)/doc/doc++/$(TARGET_BASENAME)"
+
+
+$(EXEC): $(OBJS)
+ $(C++) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+
+
+## Mac OSX makes the distinction between -dynamiclib and -bundle
+## causing us to have to make a special case here, rather than
+## just redefining the SHARED argument.
+
+ifeq ($(OS),Darwin)
+
+$(LIB): $(OBJS)
+ $(C++) $(LDFLAGS) $(LIBVERSION) -dynamiclib $(OBJS) $(LIBS) -o $@
+
+$(PLUGIN): $(OBJS)
+ $(C++) $(LDFLAGS) -bundle $(OBJS) $(LIBS) -o $@
+else
+ifeq ($(OS),HP-UX)
+# we need to explicitly tell the linker the library name - else it will
+# include paths like ../../../libosg.sl into executables
+$(LIB) $(PLUGIN) : $(OBJS)
+ $(C++) $(LDFLAGS) $(SHARED) $(OBJS) $(LIBS) -Wl,+h -Wl,$@ -o $@
+else
+$(LIB) $(PLUGIN) : $(OBJS)
+ $(C++) $(LDFLAGS) $(SHARED) $(OBJS) $(LIBS) -o $@
+
+endif # not HP-UX
+endif # not Darwin
+
+$(EXEC:=.dbg) :
+ @[ -d $(DEBUGDIR) ] || mkdir $(DEBUGDIR)
+ @cd $(DEBUGDIR); \
+ $(MAKE) -f ../GNUmakefile "DOF=$(DBGF)" TOPDIR=../${TOPDIR} \
+ THISDIR=../$(THISDIR)\
+ MAKEDEPEND=Makedepend $(EXEC)
+ @$(MAKE) LNSRC=$(DEBUGDIR)/$(EXEC)$(EXE_EXT) LNDEST=$(BININST)/$(OS)$(ARCH)/$(EXEC)$(EXE_EXT) __link
+
+$(LIB:=.dbg) : $(PLUGIN:=.dbg)
+ @[ -d $(DEBUGDIR) ] || mkdir $(DEBUGDIR)
+ @[ -d "$(TOPDIR)/lib/$(OS)$(ARCH)" ] || mkdir -p $(TOPDIR)/lib/$(OS)$(ARCH)
+ @cd $(DEBUGDIR);\
+ $(MAKE) -f ../GNUmakefile "DOF=$(DBGF)" TOPDIR=../${TOPDIR} \
+ THISDIR=../$(THISDIR)\
+ MAKEDEPEND=Makedepend $(LIB)
+ @$(MAKE) LNSRC=$(DEBUGDIR)/$(LIB) LNDEST=$(LIBINST)/$(OS)$(ARCH)/$(LIB) __link
+
+$(PLUGIN:=.dbg) :
+ @[ -d $(DEBUGDIR) ] || mkdir $(DEBUGDIR)
+ @cd $(DEBUGDIR); \
+ $(MAKE) -f ../GNUmakefile "DOF=$(DBGF)" TOPDIR=../${TOPDIR} \
+ THISDIR=../$(THISDIR)\
+ MAKEDEPEND=Makedepend $(PLUGIN)
+ @$(MAKE) LNSRC=$(DEBUGDIR)/$(PLUGIN) LNDEST=$(PLUGININST)/$(PLUGIN) __link
+
+$(EXEC:=.opt) :
+ @[ -d $(OPTDIR) ] || mkdir $(OPTDIR)
+ @cd $(OPTDIR); \
+ $(MAKE) -f ../GNUmakefile DOF=$(OPTF) TOPDIR=../${TOPDIR} \
+ THISDIR=../$(THISDIR)\
+ MAKEDEPEND=Makedepend $(EXEC)
+ @$(MAKE) LNSRC=$(OPTDIR)/$(EXEC)$(EXE_EXT) LNDEST=$(BININST)/$(OS)$(ARCH)/$(EXEC)$(EXE_EXT) __link
+
+
+$(LIB:=.opt) :
+ @[ -d $(OPTDIR) ] || mkdir -p $(OPTDIR)
+ @[ -d "$(TOPDIR)/lib/$(OS)$(ARCH)" ] || mkdir -p $(TOPDIR)/lib/$(OS)$(ARCH)
+ @cd $(OPTDIR);\
+ $(MAKE) -f ../GNUmakefile DOF=$(OPTF) TOPDIR=../${TOPDIR} \
+ THISDIR=../$(THISDIR)\
+ MAKEDEPEND=Makedepend $(LIB)
+ @$(MAKE) LNSRC=$(OPTDIR)/$(LIB) LNDEST=$(LIBINST)/$(OS)$(ARCH)/$(LIB) __link
+
+$(PLUGIN:=.opt) :
+ @[ -d $(OPTDIR) ] || mkdir -p $(OPTDIR)
+ @cd $(OPTDIR); \
+ $(MAKE) -f ../GNUmakefile DOF=$(OPTF) TOPDIR=../${TOPDIR} \
+ THISDIR=../$(THISDIR)\
+ MAKEDEPEND=Makedepend $(PLUGIN)
+ @$(MAKE) LNSRC=$(OPTDIR)/$(PLUGIN) LNDEST=$(PLUGININST)/$(PLUGIN) __link
+
+
+## Revamped method for making Makedepend files
+## Under this method, Makedepend simply includes
+## all dependency files which are built for each
+## individual source file. At update, only the individual
+## dependency file is updated rather than the whole of Makedepend
+
+Makedepend : $(CXXFILES) $(CFILES)
+ifeq ($(OS),IRIX)
+ touch $@
+else
+ @ touch $@
+ @if [ ! -d .depend ] ; then \
+ mkdir .depend;\
+ depfiles="$+";\
+ else\
+ depfiles="$?";\
+ fi;\
+ if [ ! -z "$$depfiles" ]; then \
+ for f in $$depfiles; do \
+ echo "$(C++) $(DEPARG) $(INC) $$f pipeto .depend/`basename $$f`"; \
+ $(C++) $(DEPARG) $(INC) $$f > .depend/`basename $$f`; \
+ grep $$f $@ || echo include .depend/`basename $$f` >> Makedepend ;\
+ done;\
+ fi
+endif
+
+
+ifeq (0,1) ##### OLD WAY : Keep until we've proven that this doesn't trip up
+ ##### on other OS's.
+ Makedepend : $(CXXFILES) $(CFILES)
+ ifeq ($(OS),IRIX)
+ touch $@
+ else
+ $(C++) $(INC) $(DEPARG) $^ > $(MAKEDEPEND)
+ endif
+
+endif
+
+
+.SUFFIXES: .cpp .c .o
+.cpp.o:
+ $(C++) $(CXXFLAGS) -c $<
+.c.o:
+ $(CC) $(CXXFLAGS) -c $<
+
+depend : $(MAKEDEPEND)
+
+__link :
+ @sh $(TOPDIR)/Make/dolink.sh $(TOPDIR) $(LNSRC) $(LNDEST) "$(LINK)"
+
+__instfiles :
+ @echo $(INSTFILES)
+
+sinclude $(MAKEDEPEND)
+
diff --git a/ossimPlanet/Make/maketoprule b/ossimPlanet/Make/maketoprule
new file mode 100644
index 0000000..d91f797
--- /dev/null
+++ b/ossimPlanet/Make/maketoprule
@@ -0,0 +1,20 @@
+veryclean: clobber cleanlib cleanbin cleandoc
+
+cleanlib:
+ rm -rf $(TOPDIR)/lib
+
+cleanbin:
+ rm -rf $(TOPDIR)/bin
+
+cleandoc:
+ rm -rf $(TOPDIR)/doc/*
+
+rpm:
+ $(TOPDIR)/Make/makerpms "$(OS)" \
+ "$(TOPDIR)" \
+ "$(INST_LIBS)" \
+ "$(INST_INCLUDE)" \
+ "$(INST_EXAMPLES)" \
+ "$(INST_SRC)" \
+ "$(INST_EXAMPLE_SRC)" \
+ "$(INST_DOC)"
diff --git a/ossimPlanet/Make/versionrules b/ossimPlanet/Make/versionrules
new file mode 100644
index 0000000..61af727
--- /dev/null
+++ b/ossimPlanet/Make/versionrules
@@ -0,0 +1,16 @@
+#######################################################################
+##
+## VERSIONING SEMANTICS
+##
+## Version consistes of <major> . <minor> . <release> - <revision>
+## Where:
+## major : Production (0 = pre-production)
+## minor : 0-7 = Production minor, 8 = Alpha, 9 = Beta
+## release : Release tag
+## revision: Release revision - 0 = development (cutting edge).
+##
+##
+## 'make version' will print the version with a
+#######################################################################
+version :
+ @echo $(VERSION)-$(VERSION_REVISION);
diff --git a/ossimPlanet/README.txt b/ossimPlanet/README.txt
new file mode 100644
index 0000000..ded52ef
--- /dev/null
+++ b/ossimPlanet/README.txt
@@ -0,0 +1,12 @@
+
+PACKAGES required:
+
+1. OSSIM, found at ossim.org. This is the core geospatial image and corrdinate processing ngine used by ossimPlanet
+
+2. libwms. Used for WMS access. This uses libcurl for the http protocol.
+
+3. OpenSceneGraph. Found at http://www.openscenegraph.org. This is used for the 3-D visualization.
+
+
+
+
diff --git a/ossimPlanet/apps/ossimplanet-chip/ossimplanet-chip.cpp b/ossimPlanet/apps/ossimplanet-chip/ossimplanet-chip.cpp
new file mode 100644
index 0000000..df503e9
--- /dev/null
+++ b/ossimPlanet/apps/ossimplanet-chip/ossimplanet-chip.cpp
@@ -0,0 +1,496 @@
+#include <ossimPlanet/ossimPlanetApi.h>
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/init/ossimInit.h>
+#include <ossim/elevation/ossimElevManager.h>
+#include <ossim/imaging/ossimMemoryImageSource.h>
+#include <ossim/imaging/ossimJpegWriter.h>
+#include <iostream>
+#include <sstream>
+#include <osg/ArgumentParser>
+#include <osg/Texture>
+#include <osg/PositionAttitudeTransform>
+#include <osgDB/ReadFile>
+#include <osgDB/WriteFile>
+#include <osg/Drawable>
+#include <osg/io_utils>
+#include <time.h>
+#include <osgViewer/Renderer>
+#include <osgViewer/ViewerEventHandlers>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetManipulator.h>
+#include <ossimPlanet/ossimPlanetLatLonHud.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetTerrainGeometryTechnique.h>
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <ossimPlanet/ossimPlanetViewMatrixBuilder.h>
+#include <ossimPlanet/ossimPlanetCloudLayer.h>
+#include <ossimPlanet/ossimPlanetEphemeris.h>
+#include <osgGA/TrackballManipulator>
+#include <osgGA/FlightManipulator>
+#include <osgGA/DriveManipulator>
+#include <osgGA/KeySwitchMatrixManipulator>
+#include <osgGA/StateSetManipulator>
+#include <osgGA/AnimationPathManipulator>
+#include <osgGA/TerrainManipulator>
+#include <ossimPlanet/ossimPlanetAnimationPath.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <osg/Geometry>
+#include <osg/MatrixTransform>
+#include <osg/LineWidth>
+#include <osgText/Text>
+#include <osgUtil/CullVisitor>
+#include <osg/ClipPlane>
+
+#include <osg/Program>
+#include <osg/Uniform>
+
+#include <osg/Geode>
+#include <osg/Geometry>
+
+
+class CustomRenderer : public osgViewer::Renderer
+{
+public:
+ CustomRenderer( osg::Camera* camera )
+ : osgViewer::Renderer(camera), _cullOnly(true)
+ {
+ }
+
+ void setCullOnly(bool on) { _cullOnly = on; }
+
+ virtual void operator ()( osg::GraphicsContext* )
+ {
+ if ( _graphicsThreadDoesCull )
+ {
+ if (_cullOnly)
+ {
+ cull();
+ }
+ else
+ {
+ cull_draw();
+ }
+ }
+ }
+ virtual void cull()
+ {
+ osgUtil::SceneView* sceneView = _sceneView[0].get();
+ if ( !sceneView || _done )
+ return;
+
+ updateSceneView( sceneView );
+
+ osgViewer::View* view = dynamic_cast<osgViewer::View*>( _camera->getView() );
+ if ( view )
+ sceneView->setFusionDistance( view->getFusionDistanceMode(), view->getFusionDistanceValue() );
+ sceneView->inheritCullSettings( *(sceneView->getCamera()) );
+ sceneView->cull();
+ }
+ bool _cullOnly;
+};
+
+int main(int argc, char* argv[])
+{
+ ossimInit::instance()->initialize(argc, argv);
+
+ osg::ref_ptr<ossimPlanetGrid> grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_CAP);
+
+ ossimString tempString;
+ osg::ArgumentParser::Parameter stringParam(tempString);
+
+ osg::ArgumentParser arguments(&argc,argv);
+ arguments.getApplicationUsage()->addCommandLineOption("--terrain-requests-per-frame",
+ "Specify the number of requests to apply to the terrain graph per frame");
+ arguments.getApplicationUsage()->addCommandLineOption("--terrain-threads",
+ "Specify the number of terrain threads to use Specify between 1 and 3 for now");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-image", "Image to add");
+ arguments.getApplicationUsage()->addCommandLineOption("--polar-cap", "Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--osg-view", "no ossimPlanet just use osg's readNode to add to scene");
+ arguments.getApplicationUsage()->addCommandLineOption("--split-merge-speed", "enumeration that maps to split merge ratio. Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, and HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--elevation-density-type", "enumeration that maps amount of elevation posts to use per patch. Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, and HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--texture-density-type", "enumeration that maps amount of texture samples to use per patch. Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, and HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--elevation-exaggeration", "Scales the elevation by this factor");
+ arguments.getApplicationUsage()->addCommandLineOption("--cull-amount", "Sets the amount of culling in the graph. Values can be low, medium, high");
+ arguments.getApplicationUsage()->addCommandLineOption("--min-time-compile", "sets the minimum time to compile per frame in seconds. So 3 milliseconds is .003");
+ arguments.getApplicationUsage()->addCommandLineOption("--animation-path", "Reads in an animation path");
+ arguments.getApplicationUsage()->addCommandLineOption("--animation-node", "Reads in an animation node");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-kml", "Adds a kml layer to planet");
+ arguments.getApplicationUsage()->addCommandLineOption("--moon-image", "Moon image used for the moon sprite for the Ephemeris");
+ arguments.getApplicationUsage()->addCommandLineOption("--sun-image", "Moon image used for the moon sprite for the Ephemeris");
+ arguments.getApplicationUsage()->addCommandLineOption("--visibility", "Visibility in meters");
+ arguments.getApplicationUsage()->addCommandLineOption("--fog-near", "near plane for fog attenuation in meters");
+ arguments.getApplicationUsage()->addCommandLineOption("--cloud-coverage", "integer value used to adjust the perlin noise");
+ arguments.getApplicationUsage()->addCommandLineOption("--cloud-sharpness", "float value (0..1) used to adjust the perlin noise");
+ arguments.getApplicationUsage()->addCommandLineOption("--cloud-altitude", "Altitude of the cloud");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-cloud", "float value (0..1) used to adjust the perlin noise");
+ arguments.getApplicationUsage()->addCommandLineOption("--fog-near", "near plane for fog attenuation in meters");
+
+
+
+ ossim_uint32 helpType = 0;
+
+ if ((helpType = arguments.readHelpType()))
+ {
+ arguments.getApplicationUsage()->write(std::cout, helpType);
+ return 1;
+ }
+
+
+ osg::MatrixTransform* rootScene = new osg::MatrixTransform();
+
+ // osg::DisplaySettings::instance()->setRGB(true);
+ // osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts(1);
+ ossimPlanetTerrainGeometryTechnique* technique = new ossimPlanetTerrainGeometryTechnique();
+ ossimPlanetViewer viewer(arguments);
+ ossimPlanetTerrain::CullAmountType cullAmount = ossimPlanetTerrain::HIGH_CULL;
+ ossimPlanetTerrain::SplitMergeSpeedType splitMergeSpeed = ossimPlanetTerrain::LOW_SPEED;
+ ossimPlanetTerrain::ElevationDensityType elevationDensity = ossimPlanetTerrain::LOW_ELEVATION_DENSITY;
+ ossimPlanetTerrain::TextureDensityType textureDensity = ossimPlanetTerrain::MEDIUM_TEXTURE_DENSITY;
+ std::vector<osg::ref_ptr<ossimPlanetAnimationPath> > animationPathArray;
+ std::vector<osg::ref_ptr<ossimPlanetPointModel> > pointModels;
+ std::vector<osg::ref_ptr<ossimPlanetAnimatedPointModel> > animatedPointModels;
+ osg::ref_ptr<ossimPlanetGeoRefModel> model;
+ osg::ref_ptr<ossimPlanetManipulator> manipulator = new ossimPlanetManipulator();
+ osg::ref_ptr<ossimPlanetAnnotationLayer> annotationLayer =new ossimPlanetAnnotationLayer();
+ osg::ref_ptr<ossimPlanetKmlLayer> kmlLayer;
+ std::vector<ossimFilename> kmlFiles;
+ ossimFilename flightgearFile = "";
+ osg::ref_ptr<ossimPlanet> planet;
+ double elevationExaggeration = 1.0;
+ double minTimeToCompilePerFrame = 10000;
+ ossimFilename sunTextureFile = "";
+ ossimFilename moonTextureFile = "";
+ ossim_float64 visibility = 1000000000.0;
+ ossim_float64 fogNear = 0.0;
+ ossim_int32 cloudCoverage = 20;
+ ossim_float64 cloudSharpness = .95;
+ ossim_float64 cloudAltitude = 20000;
+ bool addCloud = false;
+
+ if(arguments.read("--cloud-coverage", stringParam))
+ {
+ cloudCoverage = tempString.toDouble();
+ }
+ if(arguments.read("--cloud-sharpness", stringParam))
+ {
+ cloudSharpness = tempString.toDouble();
+ }
+ if(arguments.read("--cloud-altitude", stringParam))
+ {
+ cloudAltitude = tempString.toDouble();
+ }
+ if(arguments.read("--add-cloud"))
+ {
+ addCloud = true;
+ }
+
+ if(arguments.read("--visibility", stringParam))
+ {
+ visibility = tempString.toDouble();
+ }
+ if(arguments.read("--fog-near", stringParam))
+ {
+ fogNear = tempString.toDouble();
+ }
+ while(arguments.read("--add-kml", stringParam))
+ {
+ kmlFiles.push_back(ossimFilename(tempString));
+ }
+ if(arguments.read("--animation-node", stringParam))
+ {
+ flightgearFile = ossimFilename(tempString);
+ }
+ while(arguments.read("--animation-path", stringParam))
+ {
+ osg::ref_ptr<ossimPlanetAnimationPath> animationPath = new ossimPlanetAnimationPath;
+
+ if(animationPath->openAnimationPathByXmlDocument(ossimFilename(tempString)))
+ {
+ animationPathArray.push_back(animationPath.get());
+ }
+ }
+ if(arguments.read("--moon-image", stringParam))
+ {
+ moonTextureFile = ossimFilename(tempString);
+ }
+ if(arguments.read("--sun-image", stringParam))
+ {
+ sunTextureFile = ossimFilename(tempString);
+ }
+ if(arguments.read("--min-time-compile", stringParam))
+ {
+ minTimeToCompilePerFrame = tempString.toDouble();
+ }
+ if(arguments.read("--elevation-exaggeration", stringParam))
+ {
+ elevationExaggeration = tempString.toDouble();
+ }
+ if(arguments.read("--texture-density-type", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ textureDensity = ossimPlanetTerrain::LOW_TEXTURE_DENSITY;
+ }
+ else if(tempString == "medium_low")
+ {
+ textureDensity = ossimPlanetTerrain::MEDIUM_LOW_TEXTURE_DENSITY;
+ }
+ else if(tempString == "medium")
+ {
+ textureDensity = ossimPlanetTerrain::MEDIUM_TEXTURE_DENSITY;
+ }
+ else if(tempString == "medium_high")
+ {
+ textureDensity = ossimPlanetTerrain::MEDIUM_HIGH_TEXTURE_DENSITY;
+ }
+ else if(tempString == "high")
+ {
+ textureDensity = ossimPlanetTerrain::HIGH_TEXTURE_DENSITY;
+ }
+ }
+ if(arguments.read("--elevation-density-type", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ elevationDensity = ossimPlanetTerrain::LOW_ELEVATION_DENSITY;
+ }
+ else if(tempString == "medium_low")
+ {
+ elevationDensity = ossimPlanetTerrain::MEDIUM_LOW_ELEVATION_DENSITY;
+ }
+ else if(tempString == "medium")
+ {
+ elevationDensity = ossimPlanetTerrain::MEDIUM_ELEVATION_DENSITY;
+ }
+ else if(tempString == "medium_high")
+ {
+ elevationDensity = ossimPlanetTerrain::MEDIUM_HIGH_ELEVATION_DENSITY;
+ }
+ else if(tempString == "high")
+ {
+ elevationDensity = ossimPlanetTerrain::HIGH_ELEVATION_DENSITY;
+ }
+ }
+ if(arguments.read("--split-merge-speed", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::LOW_SPEED;
+ }
+
+ else if(tempString == "medium_low")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::MEDIUM_LOW_SPEED;
+ }
+ else if(tempString == "medium")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::MEDIUM_SPEED;
+ }
+ else if(tempString == "medium_high")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::MEDIUM_HIGH_SPEED;
+ }
+ else if(tempString == "high")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::HIGH_SPEED;
+ }
+ }
+ if(arguments.read("--polar-cap", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::LOW_CAP);
+ }
+ else if(tempString == "medium_low")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_LOW_CAP);
+ }
+ else if(tempString == "medium")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_CAP);
+ }
+ else if(tempString == "medium_high")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_HIGH_CAP);
+ }
+ else if(tempString == "high")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::HIGH_CAP);
+ }
+ }
+ if(arguments.read("--cull-amount", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "none")
+ {
+ cullAmount = ossimPlanetTerrain::NO_CULL;
+ }
+ if(tempString == "low")
+ {
+ cullAmount = ossimPlanetTerrain::LOW_CULL;
+ }
+ else if(tempString == "medium_low")
+ {
+ cullAmount = ossimPlanetTerrain::MEDIUM_LOW_CULL;
+ }
+ else if(tempString == "medium")
+ {
+ cullAmount = ossimPlanetTerrain::MEDIUM_CULL;
+ }
+ else if(tempString == "medium_high")
+ {
+ cullAmount = ossimPlanetTerrain::MEDIUM_HIGH_CULL;
+ }
+ else if(tempString == "high")
+ {
+ cullAmount = ossimPlanetTerrain::HIGH_CULL;
+ }
+ }
+
+
+ planet = new ossimPlanet();
+ model = planet->model().get();
+ osg::ref_ptr<ossimPlanetTerrain> terrain = new ossimPlanetTerrain(grid.get());
+ terrain->setTerrainTechnique(technique);
+ terrain->setCullAmountType(cullAmount);
+ terrain->setSplitMergeSpeedType(splitMergeSpeed);
+ terrain->setTextureDensityType(textureDensity);
+ terrain->setElevationDensityType(elevationDensity);
+ terrain->setElevationExaggeration(elevationExaggeration);
+ terrain->setMinimumTimeToCompilePerFrameInSeconds(minTimeToCompilePerFrame);
+ terrain->setPrecompileEnabledFlag(false);
+ //terrain->setTextureLayer(0, group);
+ terrain->initElevation();
+ planet->addChild(terrain.get());
+ planet->addChild(annotationLayer.get());
+ rootScene->addChild(planet.get());
+ viewer.setSceneData( rootScene );
+
+ osg::ref_ptr<osg::StateSet> sset = planet->getOrCreateStateSet();
+ if(arguments.read("--terrain-requests-per-frame", stringParam))
+ {
+ ossim_int32 requestsPerFrame = ossimString(tempString).toInt32();
+ if(requestsPerFrame <= 0)
+ {
+ requestsPerFrame = 1;
+ }
+ viewer.setTerrainMaxNumberOfOperationsToApplyToGraphPerFrame(requestsPerFrame);
+ }
+ while(arguments.read("--add-image", stringParam))
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(tempString);
+ if(layer.valid())
+ {
+ viewer.addImageTexture(layer.get());
+
+ }
+ }
+ viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
+ viewer.addEphemeris(ossimPlanetEphemeris::SUN_LIGHT
+ //|ossimPlanetEphemeris::MOON_LIGHT
+ //|ossimPlanetEphemeris::AMBIENT_LIGHT
+ // |ossimPlanetEphemeris::SUN
+ |ossimPlanetEphemeris::MOON
+ |ossimPlanetEphemeris::SKY
+ |ossimPlanetEphemeris::FOG
+ );
+ ossimLocalTm date;
+ date.now();
+ viewer.ephemeris()->setDate(date);
+
+ osg::ref_ptr<osg::GraphicsContext> pbuffer;
+ osg::Image *image = new osg::Image();
+
+ osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
+ traits->readDISPLAY();
+ traits->alpha = 8;
+ traits->width = 1920;
+ traits->height = 1080;
+ traits->pbuffer = true;
+ pbuffer = osg::GraphicsContext::createGraphicsContext(traits.get());
+ manipulator->setEventHandlingFlag(true);
+ manipulator->viewMatrixBuilder()->setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_Y);
+ viewer.setCameraManipulator(manipulator.get());
+
+ osg::ref_ptr<CustomRenderer> renderer;
+ if (pbuffer.valid())
+ {
+ osg::Camera *camera = viewer.getCamera();
+ renderer = new CustomRenderer( camera );
+ camera->setGraphicsContext(pbuffer.get());
+ camera->setDrawBuffer(GL_FRONT);
+ camera->setReadBuffer(GL_FRONT);
+ camera->setViewport(new osg::Viewport(0,0,traits->width,traits->height));
+ double fovy, aspectRatio, near, far;
+ camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, near, far);
+ double newAspectRatio = double(traits->width) / double(traits->height);
+ double aspectRatioChange = newAspectRatio / aspectRatio;
+ if (aspectRatioChange != 1.0)
+ camera->getProjectionMatrix() *=
+ osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
+
+ camera->attach(osg::Camera::COLOR_BUFFER0, image);
+ if(renderer.valid()) camera->setRenderer( renderer.get() );
+
+ viewer.realize();
+ }
+ else
+ {
+ std::cout << "Invalid pbuffer!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ exit(1);
+ }
+ double time = 0.0;
+ GLenum pixelFormat = GL_RGB;
+ bool gotTheImage = false;
+ manipulator->viewMatrixBuilder()->setLookFrom(osg::Vec3d(37,87,15000),
+ osg::Vec3d(0, 0.0, 0.0),
+ 0);
+ manipulator->viewMatrixBuilder()->setLookTo(osg::Vec3d(38,87,5500));
+
+ if(!viewer.done())
+ {
+ osg::Timer_t lastFrameTick = osg::Timer::instance()->tick();
+ viewer.frame();
+ //viewer.advance();
+ if(renderer.valid())renderer->setCullOnly( true );
+ while(viewer.getAndSetRedrawFlag(false))
+ {
+ viewer.frame();
+// viewer.eventTraversal();
+// viewer.updateTraversal();
+// viewer.renderingTraversals();
+ }
+ if(renderer.valid()) renderer->setCullOnly( false );
+ viewer.frame();
+ osg::Timer_t frameTick = osg::Timer::instance()->tick();
+ double delta = osg::Timer::instance()->delta_s(lastFrameTick, frameTick);
+ std::cout << "delta = " << delta << std::endl;
+ if(!gotTheImage)
+ {
+ unsigned char* buffer = image->data();
+ ossimRefPtr<ossimImageData> imageData = new ossimImageData(0,OSSIM_UINT8, 4, image->s(), image->t());
+ imageData->initialize();
+
+ imageData->loadTile(image->data(), ossimIrect(0,0,image->s()-1, image->t()-1), OSSIM_BIP);
+ imageData->validate();
+ ossimRefPtr<ossimMemoryImageSource> memSource = new ossimMemoryImageSource();
+ memSource->setImage(imageData.get());
+ ossimRefPtr<ossimJpegWriter> jpegWriter = new ossimJpegWriter();
+ jpegWriter->connectMyInputTo(0, memSource.get());
+ jpegWriter->setFilename(ossimFilename("/tmp/output.jpg"));
+ jpegWriter->execute();
+
+ delta = osg::Timer::instance()->delta_s(frameTick, osg::Timer::instance()->tick());
+
+ std::cout << "SAVED /tmp/output.jpg in " << delta << " seconds" <<std::endl;
+ }
+ }
+}
diff --git a/ossimPlanet/binds.act b/ossimPlanet/binds.act
new file mode 100644
index 0000000..208975e
--- /dev/null
+++ b/ossimPlanet/binds.act
@@ -0,0 +1,26 @@
+# // need to say something like this in C++ when create the iac (InteractionController)
+
+:iac tie x_mouse LON YAW
+:iac tie y_mouse LAT ZOOM PITCH
+
+:iac bind left_mousedown {:navigator rotatestart}
+:iac bind left_mouseup {:navigator rotatestop}
+:iac bind middle_mousedown {:navigator losrotatestart}
+:iac bind middle_mouseup {:navigator losrotatestop}
+:iac bind right_mousedown {:navigator loszoomstart}
+:iac bind right_mouseup {:navigator loszoomstop}
+:iac bind shift_middle_mousedown {:navigator zoomstart}
+:iac bind shift_middle_mouseup {:navigator zoomstop}
+:iac bind shift_right_mousedown {:navigator lookstart}
+:iac bind shift_right_mouseup {:navigator lookstop}
+:iac bind left_key {:navigator flystart .015625 0}
+:iac bind right_key {:navigator flystart -.015625 0.0}
+:iac bind down_key {:navigator flystart 0.0 .015625}
+:iac bind up_key {:navigator flystart 0.0 -.015625}
+:iac bind u_key {:navigator resetzoomlook}
+:iac bind z_key {:navigator recordanimation}
+:iac bind Z_key {:navigator playanimation}
+:iac bind p_key {:navigator printlatlonelev}
+:iac bind P_key {:navigator printlookcoordinates}
+:iac bind space_key {:navigator reset}
+:iac bind return_key {:navigator stop}
diff --git a/ossimPlanet/examples/GNUmakefile b/ossimPlanet/examples/GNUmakefile
new file mode 100644
index 0000000..3d18103
--- /dev/null
+++ b/ossimPlanet/examples/GNUmakefile
@@ -0,0 +1,11 @@
+TOPDIR = ..
+include $(TOPDIR)/Make/makedefs
+include $(TOPDIR)/Make/makedirdefs
+
+DIRS = $(EXAMPLE_DIRS)
+
+include $(TOPDIR)/Make/makedirrules
+include $(TOPDIR)/Make/versionrules
+include $(TOPDIR)/Make/instrules
+include $(TOPDIR)/Make/distrules
+include $(TOPDIR)/Make/helprules
diff --git a/ossimPlanet/examples/ossimplanetinfo/GNUmakefile b/ossimPlanet/examples/ossimplanetinfo/GNUmakefile
new file mode 100644
index 0000000..d5afe30
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetinfo/GNUmakefile
@@ -0,0 +1,20 @@
+TOPDIR = ../..
+include $(TOPDIR)/Make/makedefs
+
+CXXFILES =\
+ ossimplanetinfo.cpp
+
+LIBS += $(OSSIM_LIBS) -lossimPlanet -lossimPredator $(OSG_LIBS) $(OTHER_LIBS)
+
+ifeq ($(OS),Darwin)
+ LIBS += -bind_at_load
+endif
+
+INSTFILES = \
+ $(CXXFILES)\
+ GNUmakefile.inst=GNUmakefile
+LIB=
+EXEC = ossimplanetinfo
+
+include $(TOPDIR)/Make/makerules
+
diff --git a/ossimPlanet/examples/ossimplanetinfo/ossimplanetinfo.cpp b/ossimPlanet/examples/ossimplanetinfo/ossimplanetinfo.cpp
new file mode 100644
index 0000000..b2d5561
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetinfo/ossimplanetinfo.cpp
@@ -0,0 +1,93 @@
+#include <ossim/init/ossimInit.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <iostream>
+#ifdef OSSIMPLANET_ENABLE_PREDATOR
+#include <ossimPredator/ossimPredatorApi.h>
+#include <iomanip>
+
+bool printPredatorInfo(const ossimFilename& file, std::ostream& out)
+{
+ out << std::setprecision(20);
+ bool result = false;
+ ossimRefPtr<ossimPredatorVideo> video = new ossimPredatorVideo();
+ ossimRefPtr<ossimPredatorVideo::FrameInfo> frameInfo;
+ result = video->open(file);
+ if(result)
+ {
+ // look at the first couple of seconds worth of video to find a klv stream
+ //
+ ossim_uint32 maxFramesToCheck = video->videoFrameRate()*2;
+ bool foundInfo = false;
+ ossim_uint32 frameCount=0;
+ while((!foundInfo)&&
+ (frameCount <= maxFramesToCheck)&&
+ ((frameInfo = video->nextFrame()).valid()))
+ {
+ ++frameCount;
+ ossimRefPtr<ossimPredatorKlvTable> klvTable = frameInfo->klvTable();
+ if(klvTable.valid())
+ {
+ ossimGpt ulg, urg, lrg, llg;
+ ossimString prefix = "video0.frame0.";
+ foundInfo = klvTable->getCornerPoints(ulg, urg, lrg, llg);
+ if(!foundInfo)
+ {
+ ossim_float64 lat, lon, elev;
+
+ foundInfo = klvTable->getFrameCenter(lat, lon, elev);
+ if(foundInfo)
+ {
+ ulg = ossimGpt(lat, lon, elev);
+ urg = ulg;
+ lrg = ulg;
+ llg = ulg;
+ }
+ }
+ if(foundInfo)
+ {
+ out << "video0.type: ossimPredatorVideo\n"
+ << prefix << "ul_lat: " << ulg.latd() << "\n"
+ << prefix << "ul_lon: " << ulg.lond() << "\n"
+ << prefix << "ur_lat: " << urg.latd() << "\n"
+ << prefix << "ur_lon: " << urg.lond() << "\n"
+ << prefix << "lr_lat: " << lrg.latd() << "\n"
+ << prefix << "lr_lon: " << lrg.lond() << "\n"
+ << prefix << "ll_lat: " << llg.latd() << "\n"
+ << prefix << "ll_lon: " << llg.lond() << "\n";
+ }
+ }
+ }
+ }
+ return result;
+}
+#endif
+
+
+bool printVideoInfo(const ossimFilename& file, std::ostream& out)
+{
+ bool result = false;
+#ifdef OSSIMPLANET_ENABLE_PREDATOR
+ result = printPredatorInfo(file, out);
+#endif
+
+ return result;
+}
+
+int main(int argc, char* argv[])
+{
+ ossimInit::instance()->initialize(argc, argv);
+
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
+ return 0;
+ }
+ ossimFilename file(argv[1]);
+ if(printVideoInfo(file, std::cout))
+ {
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/ossimPlanet/examples/ossimplanetinfo/ossimplanetinfo.vcproj b/ossimPlanet/examples/ossimplanetinfo/ossimplanetinfo.vcproj
new file mode 100755
index 0000000..73e24cb
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetinfo/ossimplanetinfo.vcproj
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="ossimplanetinfo"
+ ProjectGUID="{ADACE05C-5874-451F-8ED8-E75884170892}"
+ RootNamespace="ossimplanetinfo"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\..\ossim_dependencies\src\3rdParty\include";"$(ProjectDir)..\..\..\ossim\include";"$(ProjectDir)..\..\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\zziplib-0.13.49";"$(ProjectDir)..\..\..\libwms\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph\include""
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CONSOLE;OSGPLANET_WITHOUT_WMS;FREETYPE_SETTING=1;GEOTIFF_ENABLED;HAVE_CONFIG_H"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(SolutionDir)bin\ossimplanetinfo.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="C:\Svs_dev_C\ossim\lib;C:\Svs_dev_C\3rdParty\lib;C:\Svs_dev_C\OpenThreads\lib\win32;C:\Svs_dev_C\Producer\lib;C:\Svs_dev_C\OpenSceneGraph\lib;C:\Svs_dev_C\gdal"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/ossimplanetinfo.pdb"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\include";"$(ProjectDir)..\..\..\ossim\include";"$(ProjectDir)..\..\..\libwms\include";"$(ProjectDir)..\..\..\ossim_dependencies\include""
+ PreprocessorDefinitions="NDEBUG;_WINDOWS;WIN32;_CONSOLE;NOMINMAX"
+ RuntimeLibrary="2"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="OpenThreads.lib osg.lib osgDB.lib osgViewer.lib osgGA.lib osgText.lib osgUtil.lib"
+ OutputFile="$(OutDir)\bin\$(ProjectName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""$(ProjectDir)..\..\..\ossim\projects\vs2005\bin\Release";"$(ProjectDir)..\..\..\ossim_dependencies\lib";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph-2.8.1\build\lib""
+ GenerateDebugInformation="false"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)\lib\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\ossimplanetinfo.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\opvLoadModel.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/ossimPlanet/examples/ossimplanetklv/GNUmakefile b/ossimPlanet/examples/ossimplanetklv/GNUmakefile
new file mode 100644
index 0000000..4db081c
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetklv/GNUmakefile
@@ -0,0 +1,20 @@
+TOPDIR = ../..
+include $(TOPDIR)/Make/makedefs
+
+CXXFILES =\
+ ossimplanetpredator.cpp
+
+LIBS += $(OSSIM_LIBS) -lossimPlanet -lossimPredator $(OSG_LIBS) $(OTHER_LIBS)
+
+ifeq ($(OS),Darwin)
+ LIBS += -bind_at_load
+endif
+
+INSTFILES = \
+ $(CXXFILES)\
+ GNUmakefile.inst=GNUmakefile
+LIB=
+EXEC = ossimplanetpredator
+
+include $(TOPDIR)/Make/makerules
+
diff --git a/ossimPlanet/examples/ossimplanetklv/ossimplanetklv.cpp b/ossimPlanet/examples/ossimplanetklv/ossimplanetklv.cpp
new file mode 100644
index 0000000..b35ed35
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetklv/ossimplanetklv.cpp
@@ -0,0 +1,179 @@
+#include <ossim/init/ossimInit.h>
+#include <ossim/base/ossimGeoidManager.h>
+#include <ossimPredator/ossimPredatorApi.h>
+#include <ossimPredator/ossimPredatorUavProjection.h>
+#include <osg/ArgumentParser>
+#include <fstream>
+int main(int argc, char* argv[])
+{
+ ossimInit::instance()->initialize(argc, argv);
+ ossimString tempString;
+ ossimString tempString2;
+ osg::ArgumentParser::Parameter stringParam(tempString);
+ osg::ArgumentParser::Parameter stringParam2(tempString2);
+
+ osg::ArgumentParser arguments(&argc,argv);
+ arguments.getApplicationUsage()->addCommandLineOption("--video",
+ "specify the input video to process");
+ arguments.getApplicationUsage()->addCommandLineOption("--animation-path-out",
+ "specify the filename to output the animation path to");
+ arguments.getApplicationUsage()->addCommandLineOption("--test-sensor-projection",
+ "Test sensor projection from KlvInfo");
+ unsigned int helpType = 0;
+ if ((helpType = arguments.readHelpType()))
+ {
+ arguments.getApplicationUsage()->write(std::cout, helpType);
+ return 1;
+ }
+ while(arguments.read("--video", stringParam))
+ {
+ if(arguments.read("--test-sensor-projection"))
+ {
+ ossimRefPtr<ossimPredatorUavProjection> proj = new ossimPredatorUavProjection;
+ ossimRefPtr<ossimPredatorVideo> predatorVideo = new ossimPredatorVideo();
+
+ if(predatorVideo->open(ossimFilename(tempString)))
+ {
+ ossim_uint32 imageWidth = predatorVideo->imageWidth();
+ ossim_uint32 imageHeight = predatorVideo->imageHeight();
+ ossimRefPtr<ossimPredatorVideo::KlvInfo> klvinfo;
+ ossim_float64 prevTime = -1.0;
+ while(( klvinfo = predatorVideo->nextKlv()).valid())
+ {
+ ossim_float64 lat,lon,elev;
+ ossim_float32 hfov;
+ ossim_float32 vfov;
+ ossim_float32 h,p,r;
+ ossim_float32 obliquityAngle;
+ ossim_float32 angleToNorth;
+ ossim_float32 slantRange;
+ ossim_float32 sensorRoll = 0.0;
+ klvinfo->table()->print(std::cout) << std::endl;
+ if(klvinfo->table()->getSensorPosition(lat, lon, elev)&&
+ klvinfo->table()->getPlatformOrientation(h,p,r))
+ {
+ if(!klvinfo->table()->getObliquityAngle(obliquityAngle))
+ {
+ obliquityAngle = 0.0;
+ }
+ if(!klvinfo->table()->getSlantRange(slantRange))
+ {
+ slantRange = 1.0;
+ }
+ bool gotHfov = true;
+ if(!klvinfo->table()->getHorizontalFieldOfView(hfov))
+ {
+ hfov = 1.0;
+ gotHfov = false;
+ }
+ if(!klvinfo->table()->getVerticalFieldOfView(vfov))
+ {
+ vfov = hfov;
+ }
+ else if(!gotHfov)
+ {
+ hfov = vfov;
+ }
+ klvinfo->table()->getSensorRollAngle(sensorRoll);
+ if(!klvinfo->table()->getAngleToNorth(angleToNorth))
+ {
+ angleToNorth = 0.0;
+ }
+ ossim_float64 value = ossimGeoidManager::instance()->offsetFromEllipsoid(ossimGpt(lat, lon, elev));
+ if(!ossim::isnan(value))
+ {
+ elev += value;
+ }
+ proj->setParameters(imageWidth,
+ imageHeight,
+ ossimGpt(lat, lon, elev),
+ ossimGpt(),
+ h, p, sensorRoll,
+ hfov,
+ vfov,
+ obliquityAngle,
+ angleToNorth,
+ 0.0,
+ 0.0);
+ ossimDpt ipt(imageWidth*.5, imageHeight*.5);
+ ossimGpt centerProj;
+ ossimGpt ul;
+ ossimGpt ur;
+ ossimGpt lr;
+ ossimGpt ll;
+ proj->lineSampleToWorld(ipt, centerProj);
+ proj->lineSampleToWorld(ossimDpt(0,0), ul);
+ proj->lineSampleToWorld(ossimDpt(imageWidth,0), ur);
+ proj->lineSampleToWorld(ossimDpt(imageWidth,imageHeight), lr);
+ proj->lineSampleToWorld(ossimDpt(imageHeight,0), ll);
+
+ std::cout << std::setprecision(15);
+ std::cout << "position = " << ossimGpt(lat, lon, elev) << std::endl;
+ std::cout << "centerGpt = " << centerProj << std::endl;
+ std::cout << "ul = " << ul << std::endl;
+ std::cout << "ur = " << ur << std::endl;
+ std::cout << "lr = " << lr << std::endl;
+ std::cout << "ll = " << ll << std::endl;
+
+// std::cout << "angle to north = " << angleToNorth << std::endl;
+// std::cout << "ObliquityAngle = " << obliquityAngle << std::endl;
+// std::cout << "hpr = " << h << ", " << p << ", " << r << std::endl;
+// std::cout << "Platform = " << ossimGpt(lat, lon, elev) << std::endl;
+// std::cout << "World point = " << centerProj << std::endl;
+ if(klvinfo->table()->getFrameCenter(lat, lon, elev))
+ {
+ std::cout << "Center frame = " << ossimGpt(lat, lon, elev) << std::endl;
+ }
+ }
+ }
+ }
+ }
+
+ if(arguments.read("--animation-path-out", stringParam2))
+ {
+ std::ofstream out(tempString2.c_str());
+ if(out.good())
+ {
+ out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ out << "<AnimationPath>";
+ out << "<GeospatialPath timeUnit='seconds' positionType='latlonhgt' orientationType='lsrhpr'>";
+ out << "<description>Cool path</description>";
+ out << "<coordinates>";
+
+ ossimRefPtr<ossimPredatorVideo> predatorVideo = new ossimPredatorVideo();
+
+ if(predatorVideo->open(ossimFilename(tempString)))
+ {
+ ossim_float32 srange;
+ ossimRefPtr<ossimPredatorVideo::KlvInfo> klvinfo;
+ ossim_float64 prevTime = -1.0;
+ while(( klvinfo = predatorVideo->nextKlv()).valid())
+ {
+ klvinfo->table()->getSlantRange(srange);
+ //std::cout << "range === " << srange << std::endl;
+ if(!ossim::almostEqual(klvinfo->time(), prevTime, 1e-10))
+ {
+ prevTime = klvinfo->time();
+ ossimString sensorLat, sensorLon, sensorAlt, h,p,r;
+ if(klvinfo->table()->valueAsString(sensorLat, KLV_KEY_SENSOR_LATITUDE)&&
+ klvinfo->table()->valueAsString(sensorLon, KLV_KEY_SENSOR_LONGITUDE)&&
+ klvinfo->table()->valueAsString(sensorAlt, KLV_KEY_SENSOR_TRUE_ALTITUDE))
+ {
+ klvinfo->table()->valueAsString(h,KLV_KEY_PLATFORM_HEADING_ANGLE);
+ klvinfo->table()->valueAsString(p,KLV_KEY_PLATFORM_PITCH_ANGLE);
+ klvinfo->table()->valueAsString(r,KLV_KEY_PLATFORM_ROLL_ANGLE);
+
+ double headingAdjust = h.toDouble();
+ if(headingAdjust > 180.0) headingAdjust -= 360.0;
+ out << klvinfo->time() << ","
+ << sensorLat <<"," << sensorLon << "," <<sensorAlt.toDouble()*0.304801 << ","
+ << headingAdjust << "," << p.toDouble() << "," << r.toDouble() <<std::endl;
+ }
+ }
+ }
+ }
+ out << "</coordinates></GeospatialPath></AnimationPath>";
+ }
+ }
+ }
+}
diff --git a/ossimPlanet/examples/ossimplanettest/GNUmakefile b/ossimPlanet/examples/ossimplanettest/GNUmakefile
new file mode 100644
index 0000000..e025281
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanettest/GNUmakefile
@@ -0,0 +1,20 @@
+TOPDIR = ../..
+include $(TOPDIR)/Make/makedefs
+
+CXXFILES =\
+ ossimplanettest.cpp
+
+LIBS += $(OSSIM_LIBS) -lossimPlanet $(OSG_LIBS) $(OTHER_LIBS)
+
+ifeq ($(OS),Darwin)
+ LIBS += -bind_at_load
+endif
+
+INSTFILES = \
+ $(CXXFILES)\
+ GNUmakefile.inst=GNUmakefile
+LIB=
+EXEC = ossimplanettest
+
+include $(TOPDIR)/Make/makerules
+
diff --git a/ossimPlanet/examples/ossimplanettest/ossimplanettest.cpp b/ossimPlanet/examples/ossimplanettest/ossimplanettest.cpp
new file mode 100644
index 0000000..0957d4d
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanettest/ossimplanettest.cpp
@@ -0,0 +1,1657 @@
+#include <ossim/init/ossimInit.h>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetManipulator.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetTerrainGeometryTechnique.h>
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <ossimPlanet/ossimPlanetViewMatrixBuilder.h>
+#include <ossimPlanet/ossimPlanetEphemeris.h>
+#include <ossimPlanet/ossimPlanetOssimImageLayer.h>
+#include <osgDB/ReadFile>
+#include <osgGA/GUIEventHandler>
+#include <osg/Camera>
+#include <osg/CameraNode>
+#include <osg/MatrixTransform>
+#include <osg/Geode>
+#include <osgText/Text>
+#include <osgText/Font>
+#include <osg/PolygonMode>
+#include <osgViewer/ViewerEventHandlers>
+#include <ossimPlanet/ossimPlanetLatLonHud.h>
+#include <ossimPlanet/ossimPlanetApi.h>
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/init/ossimInit.h>
+#include <ossim/elevation/ossimElevManager.h>
+#include <ossim/base/ossimGeoidEgm96.h>
+#include <iostream>
+#include <sstream>
+#include <osg/ArgumentParser>
+#include <osg/Texture>
+#include <osg/PositionAttitudeTransform>
+#include <osgDB/ReadFile>
+#include <osg/Drawable>
+#include <osg/io_utils>
+#include <time.h>
+#include <osgViewer/ViewerEventHandlers>
+#include <osgGA/TrackballManipulator>
+#include <osgGA/FlightManipulator>
+#include <osgGA/DriveManipulator>
+#include <osgGA/KeySwitchMatrixManipulator>
+#include <osgGA/StateSetManipulator>
+#include <osgGA/AnimationPathManipulator>
+#include <osgGA/TerrainManipulator>
+#include <ossimPlanet/ossimPlanetAnimationPath.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <osg/Geometry>
+#include <osg/LineWidth>
+#include <osgUtil/CullVisitor>
+#include <osg/ClipPlane>
+#include <osg/Program>
+#include <osg/Uniform>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/PolygonMode>
+#include <osg/ref_ptr>
+#include <osg/Texture>
+#include <osg/Texture2D>
+#include <osg/TextureRectangle>
+#include <osg/TextureCubeMap>
+#include <ossimPlanet/ossimPlanetCloudLayer.h>
+
+osg::Node* loadFlightGearModel(const ossimFilename& file,
+ ossimPlanetGeoRefModel* model, double scale = 1.0)
+{
+ osg::MatrixTransform* orientedModel = new osg::MatrixTransform;
+ osg::Node* flightgearModel = osgDB::readNodeFile(file.c_str(), 0);
+ osg::Matrixd mr;
+ osg::Matrixd ms;
+ double adjustedScale = scale/model->getNormalizationScale();
+ ms.makeScale(osg::Vec3d(adjustedScale, adjustedScale, adjustedScale));
+ mr.makeRotate(osg::DegreesToRadians(-90.0), osg::Vec3d(0.0,0.0,1.0),
+ osg::DegreesToRadians(-90.0), osg::Vec3d(0.0,1.0,0.0),
+ osg::DegreesToRadians(0.0), osg::Vec3d(1.0,0.0,0.0));
+ orientedModel->setMatrix(ms*mr);
+ if(flightgearModel)
+ {
+ orientedModel->addChild(flightgearModel);
+ }
+ return orientedModel;
+}
+
+class TestHandler : public osgGA::GUIEventHandler
+{
+public:
+ enum TestStage
+ {
+ OSSIMPLANET_INIT_TERRAIN = 0,
+
+ OSSIMPLANET_SET_GEOID,
+ OSSIMPLANET_SET_ELEVATION_DENSITY,
+ OSSIMPLANET_SET_CAP_LOCATION,
+ OSSIMPLANET_ADD_IMAGE_TEXTURE,
+ OSSIMPLANET_ADD_FLORIDA_DATA,
+ OSSIMPLANET_ADD_REMOVE_TEXTURE_LAYER,
+ OSSIMPLANET_SET_TEXTURE_DENSITY,
+ OSSIMPLANET_ADD_ANNOTATION_NODE,
+ OSSIMPLANET_ADJUST_HEADING,
+ OSSIMPLANET_ADJUST_PITCH,
+ OSSIMPLANET_ADJUST_ROLL,
+ OSSIMPLANET_ADD_ELEVATION,
+ OSSIMPLANET_ELEVATION_EXAGGERATION,
+ OSSIMPLANET_INITIALIZE_EPHEMERIS,
+ OSSIMPLANET_ADD_CLOUDS,
+ OSSIMPLANET_ADD_FOG,
+ OSSIMPLANET_EPHEMERIS_ANIMATE,
+ OSSIMPLANET_ANIMATION_PATH,
+ OSSIMPLANET_ANIMATION_PATH2,
+ OSSIMPLANET_LOOKFROM,
+ OSSIMPLANET_LOOKTO,
+ OSSIMPLANET_LOOKTO_DISPLACEMENT,
+ OSSIMPLANET_LOOKFROM_CONVERSION,
+ OSSIMPLANET_LOOKFROM_CONVERSION_RANGE_FLATTEN,
+ OSSIMPLANET_LOOKTO_ALONG_AXIS,
+ OSSIMPLANET_LAST_TEST
+ };
+
+ enum texture_density
+ {
+ low_texture = 0,
+ medium_low_texture,
+ medium_texture,
+ medium_high_texture,
+ high_texture,
+ last_texture
+ };
+
+ enum elevation_density
+ {
+ low_elevation = 0,
+ medium_low_elevation,
+ medium_elevation,
+ medium_high_elevation,
+ high_elevation,
+ last_elevation
+ };
+
+ enum cap
+ {
+ low_cap = 0,
+ medium_low_cap,
+ medium_cap,
+ medium_high_cap,
+ high_cap,
+ last_cap
+ };
+
+ enum AnimationFromMode
+ {
+ ANIMATION_FROM_INIT = 0,
+ RELATIVE_FROM_GLOBAL_RANGE_NONE,
+ RELATIVE_FROM_NONE,
+ RELATIVE_FROM_HEADING,
+ ANIMATION_FROM_STOP,
+ RELATIVE_FROM_PITCH,
+ RELATIVE_FROM_ROLL,
+ RELATIVE_FROM_ALL,
+ FROM_DISPLACEMENT_XYPLANE_RELATIVE_ALL_AXIS,
+ FROM_DISPLACEMENT_XYPLANE_RELATIVE_NONE_AXIS,
+ FROM_DISPLACEMENT_ZXPLANE_RELATIVE_ALL_AXIS,
+ FROM_DISPLACEMENT_ZXPLANE_RELATIVE_NONE_AXIS,
+ ANIMATION_FROM_LAST
+ };
+
+ enum AnimationToMode
+ {
+ ANIMATION_TO_MODE_INIT = 0,
+ ANIMATION_TO_BOTH_MOVING_NO_RELATVE,
+ ANIMATION_TO_LAST
+ };
+ enum FogVisibilityMode
+ {
+ FOG_CLEAR= 0,
+ FOG_VERY_LIGHT,
+ FOG_LIGHT,
+ FOG_MEDIUM,
+ FOG_MEDIUM_HEAVY,
+ FOG_HEAVY,
+ FOG_LAST
+ };
+
+ TestHandler()
+ :
+ theFontName("arial.ttf"),
+ thePlanetManipulator(new ossimPlanetManipulator),
+ theTestStage(-1),
+ theSwitchModeKey('m'),
+ theMaxTestStages(2),
+ theUpdateHudTextFlag(true),
+ theLookModeDuration(5.0)
+ {
+ }
+ ossim_float64 simtime()const
+ {
+ return theSimTime;
+ }
+ virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
+ void setRootDirectory(const ossimFilename& rootDir)
+ {
+ theRootDirectory = rootDir;
+ }
+protected:
+ void updateCurrentStage(ossimPlanetViewer* viewer);
+ void setupStage(ossimPlanetViewer* viewer);
+ void initScene(ossimPlanetViewer* viewer);
+ void updateText()
+ {
+ theHudText->setText(theHudTextString.c_str());
+ // puts the text in the lower left corner.
+ osg::BoundingBox bb = osg::BoundingBox();
+ bb.expandBy(theHudText->getBound());
+ theHudText->setPosition(osg::Vec3d(5.0,bb.yMax()-bb.yMin(),0.0));
+ }
+ void updateHudCoordinatesIfNeeded(ossimPlanetViewer* viewer)
+ {
+ // get master camera
+ osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
+ osg::ref_ptr<osg::Viewport> masterViewport = camera->getViewport();
+ // now make sure the viewport is mirrored
+ //
+ double x = masterViewport->x();
+ double y = masterViewport->y();
+ double w = masterViewport->width();
+ double h = masterViewport->height();
+
+ if(!ossim::almostEqual(theHudViewport->x(), x)||
+ !ossim::almostEqual(theHudViewport->y(), y)||
+ !ossim::almostEqual(theHudViewport->width(), w)||
+ !ossim::almostEqual(theHudViewport->height(), h))
+ {
+ theHudViewport->setViewport(x,y,w,h);
+ theHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(theHudViewport->x(),
+ theHudViewport->width(),
+ theHudViewport->y(),
+ theHudViewport->height()));
+ updateText();
+ }
+ }
+ osg::ref_ptr<osg::CameraNode> theHudCamera;
+ osg::ref_ptr<osgText::Text> theHudText;
+ std::string theFontName;
+ osg::ref_ptr<osgText::Font> theFont;
+ osg::ref_ptr<osg::Viewport> theHudViewport;
+ osg::ref_ptr<osg::MatrixTransform> theRootScene;
+ osg::ref_ptr<ossimPlanetManipulator> thePlanetManipulator;
+ ossim_int32 theTestStage;
+ char theSwitchModeKey;
+ ossim_int32 theMaxTestStages;
+ bool theUpdateHudTextFlag;
+ ossimString theHudTextString;
+ osg::ref_ptr<osg::Node> theFlightGearModel;
+ osg::ref_ptr<osg::MatrixTransform> theFlightGearModelScaleTransform1;
+ osg::ref_ptr<ossimPlanetPointModel> thePointModel1;
+ osg::ref_ptr<ossimPlanetPointModel> thePointModel2;
+ ossim_float64 theLookModeDuration;
+ ossimFilename theRootDirectory;
+
+ std::queue<ossimFilename> theTexturesToTest;
+
+ double theSimTime;
+ double theDuration;
+ osg::Timer_t theStartTick;
+ osg::Timer_t theStartTick2;
+ osg::Timer_t lastHeadingTick;
+ osg::Timer_t theLastAnimationModeTick;
+ ossim_uint32 theAnimationFromMode;
+ ossim_uint32 theAnimationToMode;
+ ossim_uint32 texture_density;
+ ossim_uint32 elevation_density;
+ ossim_uint32 cap_location;
+ ossim_uint32 fogMode;
+
+ ossimPlanetTextureLayerGroup* theAddRemoveLayer;
+ ossimString theSwapFile1;
+ ossimString theSwapFile2;
+#if 0
+ ossimPlanetTextureLayerGroup* theSwapTestGroup;
+ ossim_int32 theSwapTestIndex1;
+ ossim_int32 theSwapTestIndex2;
+#endif
+};
+
+bool TestHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
+{
+ ossimPlanetViewer* viewer = dynamic_cast<ossimPlanetViewer*>(&aa);
+ if(viewer)
+ {
+ switch(ea.getEventType())
+ {
+ case osgGA::GUIEventAdapter::FRAME:
+ {
+ if(!theHudCamera.valid())
+ {
+ initScene(viewer);
+ }
+ updateHudCoordinatesIfNeeded(viewer);
+ updateCurrentStage(viewer);
+ if(theUpdateHudTextFlag)
+ {
+ theUpdateHudTextFlag = false;
+ updateText();
+ }
+ break;
+ }
+ case osgGA::GUIEventAdapter::KEYDOWN:
+ {
+ if(ea.getKey() == theSwitchModeKey)
+ {
+ ++theTestStage;
+ theTestStage = theTestStage % OSSIMPLANET_LAST_TEST;
+ setupStage(viewer);
+ return true;
+ }
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ return false; // go ahead and not consume any events and let them pass.
+}
+
+void TestHandler::updateCurrentStage(ossimPlanetViewer* viewer)
+{
+ switch(theTestStage)
+ {
+ case OSSIMPLANET_SET_TEXTURE_DENSITY:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ bool textureDensityChanged = false;
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > theDuration)
+ {
+ ++texture_density;
+ texture_density = texture_density%last_texture;
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+
+ theUpdateHudTextFlag = true;
+ textureDensityChanged = true;
+ switch(texture_density)
+ {
+ case low_texture:
+ {
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::LOW_TEXTURE_DENSITY);
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "setTextureDensity: Low Texture";
+ break;
+ }
+ case medium_low_texture:
+ {
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::MEDIUM_LOW_TEXTURE_DENSITY);
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "setTextureDensity: Medium Low Texture";
+ break;
+ }
+ case medium_texture:
+ {
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::MEDIUM_TEXTURE_DENSITY);
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "setTextureDensity: Medium Texture";
+ break;
+ }
+ case medium_high_texture:
+ {
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::MEDIUM_HIGH_TEXTURE_DENSITY);
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "setTextureDensity: Medium High Texture";
+ break;
+ }
+ case high_texture:
+ {
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::HIGH_TEXTURE_DENSITY);
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "setTextureDensity: High Texture";
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case OSSIMPLANET_ADD_REMOVE_TEXTURE_LAYER:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ if(osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick()) > theDuration)
+ {
+ std::swap(theSwapFile1, theSwapFile2);
+ theAddRemoveLayer->removeLayers(0, theAddRemoveLayer->numberOfLayers(), false);
+ osg::ref_ptr<ossimPlanetTextureLayer> layer1 = ossimPlanetTextureLayerRegistry::instance()->createLayer(theSwapFile1);
+ osg::ref_ptr<ossimPlanetTextureLayer> layer2 = ossimPlanetTextureLayerRegistry::instance()->createLayer(theSwapFile2);
+
+ theAddRemoveLayer->addTop(layer1);
+ theAddRemoveLayer->addTop(layer2);
+ theHudTextString = "Swapping data";
+ theStartTick = osg::Timer::instance()->tick();
+ }
+#if 0
+ if(theSwapTestGroup&&
+ (theSwapTestIndex1>=0)&&
+ (theSwapTestIndex2>=0))
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ if(osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick()) > theDuration)
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> savedLayer = theSwapTestGroup->layer(theSwapTestIndex1);
+ osg::ref_ptr<ossimPlanetTextureLayer> savedLayer2 = theSwapTestGroup->layer(theSwapTestIndex2);
+ theSwapTestGroup->swapLayers(theSwapTestIndex1, theSwapTestIndex2);
+ std::swap(theSwapTestIndex1, theSwapTestIndex2);
+ theStartTick = osg::Timer::instance()->tick();
+ theUpdateHudTextFlag = true;
+ theHudTextString = "Swap texture: " + ossimString::toString(theSwapTestIndex1) + " with "
+ +ossimString::toString(theSwapTestIndex2);
+#endif
+// viewer->terrainLayer()->refreshImageLayers(savedLayer->getExtents().get());
+// viewer->terrainLayer()->refreshImageLayers(savedLayer2->getExtents().get());
+#if 0
+ // now swap layers
+ //
+ osg::ref_ptr<ossimPlanetTextureLayer> savedLayer = theSwapTestGroup->layer(theSwapTestIndex1);
+ osg::ref_ptr<ossimPlanetTextureLayer> savedLayer2 = theSwapTestGroup->layer(theSwapTestIndex2);
+ theSwapTestGroup->replaceLayer(theSwapTestIndex1, savedLayer2.get());
+ theSwapTestGroup->replaceLayer(theSwapTestIndex2, savedLayer.get());
+ theHudTextString = "Swap texture: " + ossimString::toString(theSwapTestIndex1) + " with "
+ +ossimString::toString(theSwapTestIndex2);
+ std::swap(theSwapTestIndex1, theSwapTestIndex2);
+
+ theStartTick = osg::Timer::instance()->tick();
+ theUpdateHudTextFlag = true;
+ viewer->terrainLayer()->refreshImageLayers(savedLayer->getExtents().get());
+ viewer->terrainLayer()->refreshImageLayers(savedLayer2->getExtents().get());
+#endif
+// }
+// }
+ break;
+ }
+ case OSSIMPLANET_SET_ELEVATION_DENSITY:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > theDuration)
+ {
+ ++elevation_density;
+ elevation_density = elevation_density%last_elevation;
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+
+ theUpdateHudTextFlag = true;
+ switch(elevation_density)
+ {
+ case low_elevation:
+ {
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::LOW_ELEVATION_DENSITY);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setTextureDensity: Low Elevation";
+ break;
+ }
+ case medium_low_elevation:
+ {
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::MEDIUM_LOW_ELEVATION_DENSITY);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setTextureDensity: Medium Low Elevation";
+ break;
+ }
+ case medium_elevation:
+ {
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::MEDIUM_ELEVATION_DENSITY);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setTextureDensity: Medium Elevation";
+ break;
+ }
+ case medium_high_elevation:
+ {
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::MEDIUM_HIGH_ELEVATION_DENSITY);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setTextureDensity: Medium High Elevation";
+ break;
+ }
+ case high_elevation:
+ {
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::HIGH_ELEVATION_DENSITY);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setTextureDensity: High Elevation";
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case OSSIMPLANET_SET_CAP_LOCATION:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > theDuration)
+ {
+ ++elevation_density;
+ elevation_density = elevation_density%last_elevation;
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+
+ theUpdateHudTextFlag = true;
+ switch(elevation_density)
+ {
+ case low_cap:
+ {
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::LOW_CAP);
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setCapLocation: Low Cap";
+ break;
+ }
+ case medium_low_cap:
+ {
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_LOW_CAP);
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setCapLocation: Medium Low Cap";
+ break;
+ }
+ case medium_cap:
+ {
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_CAP);
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setCapLocation: Medium Cap";
+ break;
+ }
+ case medium_high_cap:
+ {
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_HIGH_CAP);
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setCapLocation: Medium High Cap";
+ break;
+ }
+
+ case high_cap:
+ {
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::HIGH_CAP);
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setCapLocation: High Cap";
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case OSSIMPLANET_ADJUST_HEADING:
+ {
+ double currentHeading = thePointModel1->lsrSpace()->heading();
+ const double timeDelta60Hertz = 1.0/60.0;
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > timeDelta60Hertz)
+ {
+ currentHeading += (360*timeDelta60Hertz);
+ currentHeading = fmod(currentHeading, 360.0);
+ thePointModel1->lsrSpace()->setHeadingPitchRoll(osg::Vec3d(currentHeading,0,0));
+ theHudTextString = "Heading: " + ossimString::toString(currentHeading) + " degrees";
+ theUpdateHudTextFlag = true;
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+ }
+ break;
+ }
+
+ case OSSIMPLANET_ADJUST_PITCH:
+ {
+ double currentPitch = thePointModel1->lsrSpace()->pitch()+90.0;
+ const double timeDelta60Hertz = 1.0/60.0;
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > timeDelta60Hertz)
+ {
+ currentPitch += (180*timeDelta60Hertz);
+ currentPitch = fmod(currentPitch, 180.0);
+ thePointModel1->lsrSpace()->setHeadingPitchRoll(osg::Vec3d(0.0,currentPitch-90.0,0));
+ theHudTextString = "Pitch: " + ossimString::toString(currentPitch-90.0) + " degrees";
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+ theUpdateHudTextFlag = true;
+ }
+ break;
+ }
+
+ case OSSIMPLANET_ADJUST_ROLL:
+ {
+ double currentRoll = thePointModel1->lsrSpace()->roll()+90.0;
+ const double timeDelta60Hertz = 1.0/60.0;
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > timeDelta60Hertz)
+ {
+ currentRoll += (180*timeDelta60Hertz);
+ currentRoll = fmod(currentRoll, 180.0);
+ thePointModel1->lsrSpace()->setHeadingPitchRoll(osg::Vec3d(0.0,0.0,currentRoll-90.0));
+ theHudTextString = "Roll: " + ossimString::toString(currentRoll-90.0) + " degrees";
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+ theUpdateHudTextFlag = true;
+ }
+ break;
+ }
+
+ case OSSIMPLANET_EPHEMERIS_ANIMATE:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec*3600;
+ theUpdateHudTextFlag = true;
+ theHudTextString = "Initialize ephemeris: 3600x real time";
+
+ break;
+ }
+ case OSSIMPLANET_ANIMATION_PATH:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ break;
+ }
+ case OSSIMPLANET_ANIMATION_PATH2:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ break;
+ }
+ case OSSIMPLANET_LOOKFROM:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ double range = (viewer->model()->calculateUnnormalizedLength(thePointModel1->getBound().radius()));
+ if((osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > theLookModeDuration)||
+ theAnimationFromMode == ANIMATION_FROM_INIT)
+ {
+ ++theAnimationFromMode;
+ theAnimationFromMode = theAnimationFromMode%ANIMATION_FROM_LAST;
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+
+ switch(theAnimationFromMode)
+ {
+ case RELATIVE_FROM_GLOBAL_RANGE_NONE:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range*10,
+ ossimPlanetViewMatrixBuilder::NO_ORIENTATION);
+// thePlanetManipulator->viewMatrixBuilder()->setRange(-range*10);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+ theHudTextString = "No realtive from global range mode";
+ break;
+ }
+ case RELATIVE_FROM_NONE:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range*10,
+ ossimPlanetViewMatrixBuilder::NO_ORIENTATION);
+// thePlanetManipulator->viewMatrixBuilder()->setRange(0.0);
+
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+
+ theHudTextString = "No realtive from mode";
+ break;
+ }
+ case RELATIVE_FROM_HEADING:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range*10,
+ ossimPlanetViewMatrixBuilder::HEADING);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+ theHudTextString = "Relative Heading";
+ break;
+ }
+ case ANIMATION_FROM_STOP:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->invalidate();
+ theHudTextString = "Stop Animation";
+ break;
+ }
+ case RELATIVE_FROM_PITCH:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range*10,
+ ossimPlanetViewMatrixBuilder::PITCH);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+
+ theHudTextString = "Relative Pitch";
+ break;
+ }
+ case RELATIVE_FROM_ROLL:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range*10,
+ ossimPlanetViewMatrixBuilder::ROLL);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+ theHudTextString = "Relative Roll";
+ break;
+ }
+ case RELATIVE_FROM_ALL:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range*10,
+ ossimPlanetViewMatrixBuilder::ALL_ORIENTATION);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+ theHudTextString = "Relative All";
+ break;
+ }
+ case FROM_DISPLACEMENT_XYPLANE_RELATIVE_ALL_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,0.0,rotateAmount);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ 0.0,
+ ossimPlanetViewMatrixBuilder::ALL_ORIENTATION);
+ osg::Vec3d displace = osg::Vec3d(0.0,1.0,0.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ theHudTextString = "Displacement In XY Plane Relative All Axis";
+ break;
+ }
+ case FROM_DISPLACEMENT_XYPLANE_RELATIVE_NONE_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,0.0,rotateAmount);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ 0.0,
+ ossimPlanetViewMatrixBuilder::NO_ORIENTATION);
+ osg::Vec3d displace = osg::Vec3d(0.0,1.0,0.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ theHudTextString = "Displacement In XY Plane Relative No Axis (North aligned)";
+ break;
+ }
+ case FROM_DISPLACEMENT_ZXPLANE_RELATIVE_ALL_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,rotateAmount,0.0);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ 0.0,
+ ossimPlanetViewMatrixBuilder::ALL_ORIENTATION);
+ osg::Vec3d displace = osg::Vec3d(0.0,0.0,1.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ theHudTextString = "Displacement In XZ Plane Relative All Axis";
+ break;
+ }
+ case FROM_DISPLACEMENT_ZXPLANE_RELATIVE_NONE_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,rotateAmount,0.0);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ 0.0,
+ ossimPlanetViewMatrixBuilder::NO_ORIENTATION);
+ osg::Vec3d displace = osg::Vec3d(0.0,0.0,1.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ theHudTextString = "Displacement In XZ Plane Relative No Axis (North aligned)";
+ break;
+ }
+ }
+
+ theUpdateHudTextFlag = true;
+ }
+ switch(theAnimationFromMode)
+ {
+ case FROM_DISPLACEMENT_XYPLANE_RELATIVE_ALL_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,0.0,rotateAmount);
+ osg::Vec3d displace = osg::Vec3d(0.0,1.0,0.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ break;
+ }
+ case FROM_DISPLACEMENT_XYPLANE_RELATIVE_NONE_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,0.0,rotateAmount);
+ osg::Vec3d displace = osg::Vec3d(0.0,1.0,0.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ break;
+ }
+ case FROM_DISPLACEMENT_ZXPLANE_RELATIVE_ALL_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,rotateAmount,0.0);
+ osg::Vec3d displace = osg::Vec3d(0.0,0.0,1.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ break;
+ }
+ case FROM_DISPLACEMENT_ZXPLANE_RELATIVE_NONE_AXIS:
+ {
+ double rotateAmount = osg::DegreesToRadians(360.0*(fmod(deltaSec, 3.0)/3.0));
+ osg::Matrixd rotate = osg::Matrixd::rotate(rotateAmount, 0.0,rotateAmount,0.0);
+ osg::Vec3d displace = osg::Vec3d(0.0,0.0,1.0)*rotate;
+ displace = displace*(range*2);
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(displace);
+ break;
+ }
+
+ }
+ break;
+ }
+ case OSSIMPLANET_LOOKTO:
+ {
+ double range = (viewer->model()->calculateUnnormalizedLength(thePointModel1->getBound().radius()))*10;
+
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ if((osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > 3)||
+ (theAnimationToMode == ANIMATION_TO_MODE_INIT))
+ {
+ ++theAnimationToMode;
+ theAnimationToMode = theAnimationToMode%ANIMATION_TO_LAST;
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+ switch(theAnimationToMode)
+ {
+ case ANIMATION_TO_BOTH_MOVING_NO_RELATVE:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ -range,
+ ossimPlanetViewMatrixBuilder::NO_ORIENTATION);
+ thePlanetManipulator->viewMatrixBuilder()->setLookToNode(thePointModel2.get());
+ thePlanetManipulator->viewMatrixBuilder()->setLookToLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+
+// thePlanetManipulator->viewMatrixBuilder()->setRange(-range);
+ thePlanetManipulator->viewMatrixBuilder()->setAttitudeHpr(osg::Vec3d(0,0,0));
+ theHudTextString = "Animation To Both Moving No Relative";
+ break;
+ }
+ }
+
+ theUpdateHudTextFlag = true;
+ }
+
+ break;
+ }
+ case OSSIMPLANET_LOOKTO_DISPLACEMENT:
+ case OSSIMPLANET_LOOKFROM_CONVERSION:
+ case OSSIMPLANET_LOOKFROM_CONVERSION_RANGE_FLATTEN:
+ {
+ double deltaSec = osg::Timer::instance()->delta_s(theStartTick, osg::Timer::instance()->tick());
+ theSimTime = deltaSec;
+ break;
+ }
+ case OSSIMPLANET_LOOKTO_ALONG_AXIS:
+ {
+ break;
+ }
+ case OSSIMPLANET_ADD_FOG:
+ {
+ if(osg::Timer::instance()->delta_s(theLastAnimationModeTick, osg::Timer::instance()->tick()) > theDuration)
+ {
+ theLastAnimationModeTick = osg::Timer::instance()->tick();
+ ++fogMode;
+ fogMode = fogMode%FOG_LAST;
+
+ switch(fogMode)
+ {
+ case FOG_CLEAR:
+ {
+ viewer->ephemeris()->setFogEnableFlag(false);
+ theHudTextString = "Fog: Clear Day";
+ theUpdateHudTextFlag = true;
+ break;
+ }
+ case FOG_VERY_LIGHT:
+ {
+ viewer->ephemeris()->setFogEnableFlag(true);
+ viewer->ephemeris()->setVisibility(1000000);
+ theHudTextString = "Fog: Very Light";
+ theUpdateHudTextFlag = true;
+ break;
+ }
+ case FOG_LIGHT:
+ {
+ theHudTextString = "Fog: Light";
+ theUpdateHudTextFlag = true;
+ viewer->ephemeris()->setVisibility(500000);
+ break;
+ }
+ case FOG_MEDIUM:
+ {
+ theHudTextString = "Fog: Medium Fog";
+ theUpdateHudTextFlag = true;
+ viewer->ephemeris()->setVisibility(200000);
+ break;
+ }
+ case FOG_MEDIUM_HEAVY:
+ {
+ theHudTextString = "Fog: Medium Heavy Fog";
+ theUpdateHudTextFlag = true;
+ viewer->ephemeris()->setVisibility(100000);
+ break;
+ }
+ case FOG_HEAVY:
+ {
+ theHudTextString = "Fog: Heavy Fog";
+ theUpdateHudTextFlag = true;
+ viewer->ephemeris()->setVisibility(50000);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
+void TestHandler::setupStage(ossimPlanetViewer* viewer)
+{
+ theUpdateHudTextFlag = true;
+ switch (theTestStage)
+ {
+ // Init Terrain
+ case OSSIMPLANET_INIT_TERRAIN:
+ {
+ // clear pointers that need clearing
+ //
+ thePointModel1 = 0;
+ thePointModel2 = 0;
+ theFlightGearModel = 0;
+ theFlightGearModelScaleTransform1 = 0;
+ thePlanetManipulator = 0;
+ if(viewer->planet())
+ {
+ viewer->planet()->removeChildren(0, viewer->planet()->getNumChildren());
+ }
+ viewer->setSceneData(0);
+ viewer->setCameraManipulator(0);
+ viewer->removeEphemeris();
+
+ // done clearing pointers
+
+ // Now init the new pointers
+ //
+ thePlanetManipulator = new ossimPlanetManipulator;
+ ossimPlanet* planet = new ossimPlanet;
+ theRootScene = new osg::MatrixTransform();
+ theRootScene->addChild(planet);
+ theRootScene->addChild(theHudCamera.get());
+ viewer->setSceneData(theRootScene.get());
+ viewer->setCameraManipulator(thePlanetManipulator.get());
+ viewer->planet()->addChild(new ossimPlanetTerrain);
+
+ // latLon Hud Overlay
+ //ossimPlanetLatLonHud* latLonHud = new ossimPlanetLatLonHud();
+ //viewer->planet()->addChild(latLonHud);
+
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(0.0,
+ -89.999999999999,
+ 20410038.400000,
+ 0,
+ 0,
+ 0,
+ 0.0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ theHudTextString = "Terrain Test";
+ theUpdateHudTextFlag = true;
+ viewer->planet()->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON);
+
+ // for any other stage we should have a root scene
+ if(!theRootScene.valid()) return;
+
+ viewer->addEphemeris(ossimPlanetEphemeris::SUN_LIGHT|
+ ossimPlanetEphemeris::SKY);
+
+ break;
+ }
+
+ // Set Geoid
+ case OSSIMPLANET_SET_GEOID:
+ {
+ ossimGeoidEgm96* geoid = new ossimGeoidEgm96(theRootDirectory.dirCat("geoid/egm96.grd"));
+ viewer->planet()->model()->setGeoid(geoid);
+
+ viewer->terrainLayer()->setElevationExaggeration(10000);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setGeoid: " + theRootDirectory + "/geoid/egm96.grd\n";
+ theHudTextString += "setElevationExaggeration: 10000x";
+
+ break;
+ }
+
+ // Set Elevation Density
+ case OSSIMPLANET_SET_ELEVATION_DENSITY:
+ {
+ viewer->terrainLayer()->setElevationExaggeration(1); // set elevation exaggeration back to 1x
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ osg::StateSet* state = viewer->terrainLayer()->getOrCreateStateSet();
+ osg::PolygonMode* polygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT,osg::PolygonMode::LINE);
+ state->setAttributeAndModes(polygonMode);
+
+ theSimTime = 0.0;
+ theDuration = 5.0; // duration between elevation density modes
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ elevation_density = low_elevation;
+
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::LOW_ELEVATION_DENSITY);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theUpdateHudTextFlag = true;
+ theHudTextString = "setElevationDensity: Low Elevation Density";
+
+ break;
+ }
+
+ // Set Cap Position
+ case OSSIMPLANET_SET_CAP_LOCATION:
+ {
+ viewer->terrainLayer()->setElevationDensityType(ossimPlanetTerrain::LOW_ELEVATION_DENSITY); // set elevation density back to low
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(45.000000000000,
+ -89.999999999999,
+ 20410038.400000,
+ 0,
+ 0,
+ 0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ theSimTime = 0.0;
+ theDuration = 5.0; // duration between cap location modes
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ cap_location = low_cap;
+
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::LOW_CAP);
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theUpdateHudTextFlag = true;
+ theHudTextString = "setCapLocation: Low Cap Location";
+
+ break;
+ }
+
+ // Add Image Texture
+ case OSSIMPLANET_ADD_IMAGE_TEXTURE:
+ {
+ ossimPlanetAdjustableCubeGrid* grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::LOW_CAP); // set cap position back to low
+ viewer->terrainLayer()->setGrid(grid);
+ viewer->terrainLayer()->refreshImageLayers();
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(0.000000000000,
+ -89.999999999999,
+ 20410038.400000,
+ 0,
+ 0,
+ 0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ osg::StateSet* state = viewer->terrainLayer()->getOrCreateStateSet();
+ osg::PolygonMode* polygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT,osg::PolygonMode::FILL);
+ state->setAttributeAndModes(polygonMode);
+
+ viewer->addImageTexture(theRootDirectory.dirCat("images/textures/reference/earth.jpg"));
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "addImageTexture: " + theRootDirectory + "/images/textures/reference/earth.jpg";
+
+ break;
+ }
+
+ // Add Florida Data
+ case OSSIMPLANET_ADD_FLORIDA_DATA:
+ {
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(28.239487609273,
+ -80.607619385637,
+ 1938857.036673,
+ 0,
+ 0,
+ 0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ viewer->addImageTexture(theRootDirectory.dirCat("images/textures/florida/brevard.tif"));
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theHudTextString = "addImageTexture: adding Florida data";
+
+ break;
+ }
+ case OSSIMPLANET_ADD_REMOVE_TEXTURE_LAYER:
+ {
+ theAddRemoveLayer = new ossimPlanetTextureLayerGroup;
+ viewer->addImageTexture(theAddRemoveLayer);
+ theSwapFile1 = theRootDirectory.dirCat("images/textures/sanfran/sanfran.tif").c_str();
+ theSwapFile2 = theRootDirectory.dirCat("images/textures/sanfran/sanfran_map.tif").c_str();
+
+ osg::ref_ptr<ossimPlanetTextureLayer> layer1 = ossimPlanetTextureLayerRegistry::instance()->createLayer(theSwapFile1);
+ osg::ref_ptr<ossimPlanetTextureLayer> layer2 = ossimPlanetTextureLayerRegistry::instance()->createLayer(theSwapFile2);
+ if(layer1.valid())
+ {
+ layer1->resetLookAt();
+ thePlanetManipulator->navigator()->gotoLookAt(*layer1->getLookAt(), false);
+ }
+
+ theAddRemoveLayer->addTop(layer1.get(), false);
+ theAddRemoveLayer->addTop(layer2.get(), false);
+ theHudTextString = "addImageTexture: adding Sanfran data for swap test";
+ theStartTick = osg::Timer::instance()->tick();
+ theDuration = .1; // duration between elevation density modes
+#if 0
+ osg::ref_ptr<ossimPlanetTextureLayer> layer1 = viewer->addImageTexture(theRootDirectory.dirCat("images/textures/sanfran/sanfran.tif"));
+ theSwapTestGroup = 0;
+ if(layer1.valid())
+ {
+ theSwapTestGroup = layer1->parent(0);
+ layer1->resetLookAt();
+ thePlanetManipulator->navigator()->gotoLookAt(*layer1->getLookAt(), false);
+ }
+
+ osg::ref_ptr<ossimPlanetTextureLayer> layer2 = viewer->addImageTexture(theRootDirectory.dirCat("images/textures/sanfran/sanfran_map.tif"));
+ if(layer1.valid()&&layer2.valid()&&theSwapTestGroup)
+ {
+ theSwapTestIndex1 = theSwapTestGroup->findLayerIndex(layer1.get());
+ theSwapTestIndex2 = theSwapTestGroup->findLayerIndex(layer2.get());
+ }
+ else
+ {
+ theSwapTestIndex1 = -1;
+ theSwapTestIndex2 = -1;
+ }
+ theUpdateHudTextFlag = true;
+ theHudTextString = "addImageTexture: adding Sanfran data for swap test";
+ theStartTick = osg::Timer::instance()->tick();
+ theDuration = .1; // duration between elevation density modes
+#endif
+ break;
+ }
+
+ // Set Texture Density
+ case OSSIMPLANET_SET_TEXTURE_DENSITY:
+ {
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(0.000000000000,
+ -89.999999999999,
+ 20410038.400000,
+ 0,
+ 0,
+ 0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ theSimTime = 0.0;
+ theDuration = 5.0; // duration between texture density modes
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ texture_density = low_texture;
+
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::LOW_TEXTURE_DENSITY);
+ viewer->terrainLayer()->refreshImageLayers();
+
+ theUpdateHudTextFlag = true;
+ theHudTextString = "setTextureDensity: Low Texture Density";
+
+ break;
+ }
+
+ // Add Annotation Node
+ case OSSIMPLANET_ADD_ANNOTATION_NODE:
+ {
+ viewer->terrainLayer()->setTextureDensityType(ossimPlanetTerrain::MEDIUM_TEXTURE_DENSITY); // set texture density back to medium
+ viewer->terrainLayer()->refreshImageLayers();
+
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(28.2395,
+ -80.6076,
+ 100.9824,
+ 0,
+ 0,
+ 0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ if(!viewer->annotationLayer())
+ {
+ viewer->planet()->addChild(new ossimPlanetAnnotationLayer);
+ }
+
+ else
+ {
+ viewer->annotationLayer()->removeChildren(0, viewer->annotationLayer()->getNumChildren());
+ }
+
+ if(!theFlightGearModel.valid())
+ {
+ // theFlightGearModel = loadFlightGearModel(theRootDirectory.dirCat("flight_models/f16/f16.osg"),viewer->planet()->model().get());
+ theFlightGearModel = loadFlightGearModel(theRootDirectory.dirCat("flight_models/flightgear/Aircraft/f16/Models/f16.ac"),viewer->planet()->model().get());
+ theFlightGearModelScaleTransform1 = new osg::MatrixTransform;
+ theFlightGearModelScaleTransform1->addChild(theFlightGearModel.get());
+ theFlightGearModelScaleTransform1->setMatrix(osg::Matrixd());
+
+ thePointModel1 = new ossimPlanetPointModel();
+ viewer->annotationLayer()->addChild(thePointModel1.get());
+ thePointModel1->setNode(theFlightGearModelScaleTransform1.get());
+ thePointModel1->lsrSpace()->setLatLonAltitude(osg::Vec3d(28.2395, -80.6076, 50.9824));
+ }
+
+ theHudTextString = "setNode: " + theRootDirectory + "flight_models/flightgear/Aircraft/f16/Models/f16.ac";
+
+ break;
+ }
+
+ // Adjust Heading
+ case OSSIMPLANET_ADJUST_HEADING:
+ {
+ theSimTime = 0.0;
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+
+ break;
+ }
+
+ // Adjust Pitch
+ case OSSIMPLANET_ADJUST_PITCH:
+ {
+ theSimTime = 0.0;
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+
+ break;
+ }
+
+ // Adjust Roll
+ case OSSIMPLANET_ADJUST_ROLL:
+ {
+ theSimTime = 0.0;
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+
+ break;
+ }
+
+ // Add the following...
+ // lat jog
+ // lon jog
+ // alt jog
+ // scale .5x 1x 2x
+
+ // Add Elevation
+ case OSSIMPLANET_ADD_ELEVATION:
+ {
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(35.421021580041,
+ -83.080005227486,
+ 4062.174155,
+ 0,
+ 90,
+ 0,
+ 0.0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ viewer->terrainLayer()->addElevation(theRootDirectory.dirCat("srtm30plus/"), 1);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "addElevation: " + theRootDirectory + "/srtm30plus/";
+
+ break;
+ }
+
+ case OSSIMPLANET_ELEVATION_EXAGGERATION:
+ {
+ viewer->terrainLayer()->setElevationExaggeration(1.5);
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ theHudTextString = "setElevationExaggeration: 1.5x";
+
+ break;
+ }
+
+ case OSSIMPLANET_INITIALIZE_EPHEMERIS:
+ {
+ viewer->terrainLayer()->setElevationExaggeration(1); // set elevation exaggeration back to 1x
+ viewer->terrainLayer()->refreshElevationLayers();
+
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(35.421021580041,
+ -83.080005227486,
+ 3562.174155,
+ 0,
+ 90,
+ 0,
+ 0.0,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ viewer->planet()->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON);
+
+ theSimTime = 0.0;
+
+ ossimFilename sunTextureFile = theRootDirectory.dirCat("images/icons/sun.png");
+ ossimFilename moonTextureFile = theRootDirectory.dirCat("images/icons/moon.png");
+ ossim_float64 visibility = 1000000000.0;
+ ossim_float64 fogNear = 20.0;
+
+ viewer->addEphemeris(ossimPlanetEphemeris::SUN_LIGHT
+ //|ossimPlanetEphemeris::MOON_LIGHT
+ //|ossimPlanetEphemeris::AMBIENT_LIGHT
+ |ossimPlanetEphemeris::SUN
+ |ossimPlanetEphemeris::MOON
+ |ossimPlanetEphemeris::SKY
+ |ossimPlanetEphemeris::FOG
+ );
+
+ ossimLocalTm date;
+ date.now();
+ viewer->ephemeris()->setDate(date);
+
+ viewer->ephemeris()->setApplySimulationTimeOffsetFlag(false);
+ viewer->ephemeris()->setSunTextureFromFile(sunTextureFile);
+ viewer->ephemeris()->setMoonTextureFromFile(moonTextureFile);
+ //viewer->ephemeris()->setGlobalAmbientLight(osg::Vec3d(0.1, 0.1, 0.1));
+ viewer->ephemeris()->setVisibility(visibility);
+ viewer->ephemeris()->setFogNear(fogNear);
+ viewer->ephemeris()->setFogMode(ossimPlanetEphemeris::LINEAR);
+ viewer->ephemeris()->setFogEnableFlag(true);
+
+ theHudTextString = "addEphemeris: Real Time";
+
+ break;
+ }
+
+ // Add Clouds
+ case OSSIMPLANET_ADD_CLOUDS:
+ {
+ ossim_int32 cloudCoverage = 20;
+ ossim_float64 cloudSharpness = .95;
+ ossim_float64 cloudAltitude = 20000;
+
+ osg::ref_ptr<ossimPlanetCloudLayer> cloud = new ossimPlanetCloudLayer;
+ viewer->planet()->addChild(cloud.get());
+
+ cloud->computeMesh(cloudAltitude, 32,32,1);
+ cloud->updateTexture(time(0), cloudCoverage, cloudSharpness);
+ cloud->setSpeedPerHour(60.0, OSSIM_MILES);
+ cloud->setScale(4);
+
+ theHudTextString = "Enable Clouds";
+
+ break;
+ }
+
+ // Add Fog
+ case OSSIMPLANET_ADD_FOG:
+ {
+ theSimTime = 0.0;
+ theDuration = 5.0; // duration between fog modes
+
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ fogMode = FOG_CLEAR;
+
+ viewer->ephemeris()->setFogEnableFlag(false);
+
+ theUpdateHudTextFlag = true;
+ theHudTextString = "Enable Fog: Clear Day";
+
+ break;
+ }
+
+ case OSSIMPLANET_EPHEMERIS_ANIMATE:
+ {
+ viewer->ephemeris()->setApplySimulationTimeOffsetFlag(true);
+
+ theStartTick = osg::Timer::instance()->tick();
+
+ theUpdateHudTextFlag = true;
+ theHudTextString = "addEphemeris: Sim time = 3600x";
+
+ break;
+ }
+
+ case OSSIMPLANET_ANIMATION_PATH:
+ {
+ viewer->planet()->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
+
+ osg::ref_ptr<ossimPlanetAnimationPath> animationPath = new ossimPlanetAnimationPath;
+
+ theStartTick = osg::Timer::instance()->tick();
+
+ theFlightGearModelScaleTransform1->setMatrix(osg::Matrixd::scale(50.0,50.0,50.0));
+ theFlightGearModelScaleTransform1->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
+
+ animationPath->openAnimationPathByXmlDocument(ossimFilename(theRootDirectory.dirCat("flight_paths/flight1.xml")));
+ thePointModel1->setCullingActive(false);
+ theFlightGearModelScaleTransform1->setCullingActive(false);
+
+ if(animationPath->geospatialPath()&&(!animationPath->geospatialPath()->empty()))
+ {
+ ossimPlanetAnimationPath::Tuple value = animationPath->geospatialPath()->timeTupleMap().begin()->second;
+ osg::ref_ptr<ossimPlanetLookAt> lookAt = new ossimPlanetLookAt(value.position()[0],
+ value.position()[1],
+ value.position()[2],
+ 0.0,
+ 45.0,
+ 0.0,
+ 5000,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ thePlanetManipulator->navigator()->gotoLookAt(*lookAt, false);
+
+ osg::ref_ptr<ossimPlanetAnimatedPointModel> animatedPath = new ossimPlanetAnimatedPointModel();
+
+ animationPath->setGeoRefModel(viewer->planet()->model().get());
+ animationPath->setLoopMode(osg::AnimationPath::LOOP);
+ animatedPath->setPointModel(thePointModel1.get());
+ animatedPath->setAnimationPath(animationPath.get());
+ animatedPath->setTimeScale(10.0);
+ animatedPath->setTimeOffset(0.0);
+ animatedPath->setAnimationPathColor(osg::Vec4f(2.0,0.0, 2.0, .5));
+
+ viewer->annotationLayer()->addChild(animatedPath.get());
+ theSimTime = 0.0;
+ theHudTextString = "Add Animation Path 1";
+ }
+ else
+ {
+ theHudTextString = "No points in flightpath file";
+ }
+
+ break;
+ }
+
+ case OSSIMPLANET_ANIMATION_PATH2:
+ {
+ theStartTick = osg::Timer::instance()->tick();
+ if(!thePointModel2.valid())
+ {
+ thePointModel2 = new ossimPlanetPointModel;
+ thePointModel2->setNode(theFlightGearModelScaleTransform1.get());
+ }
+ thePointModel2->setCullingActive(false);
+ osg::ref_ptr<ossimPlanetAnimationPath> animationPath2 = new ossimPlanetAnimationPath;;
+
+ animationPath2->openAnimationPathByXmlDocument(ossimFilename(theRootDirectory.dirCat("flight_paths/flight2.xml")));
+
+ osg::ref_ptr<ossimPlanetAnimatedPointModel> animatedPath2 = new ossimPlanetAnimatedPointModel();
+
+ animationPath2->setGeoRefModel(viewer->planet()->model().get());
+ animationPath2->setLoopMode(osg::AnimationPath::LOOP);
+ animatedPath2->setPointModel(thePointModel2.get());
+ animatedPath2->setAnimationPath(animationPath2.get());
+ animatedPath2->setTimeScale(62.0);
+ animatedPath2->setTimeOffset(0.0);
+ viewer->annotationLayer()->addChild(animatedPath2.get());
+ theHudTextString = "Add Animation Path 2";
+
+ break;
+ }
+
+ case OSSIMPLANET_LOOKFROM:
+ {
+
+ thePlanetManipulator->setEventHandlingFlag(true);
+ thePlanetManipulator->viewMatrixBuilder()->setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_Y);
+ theSimTime = 0.0;
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ theAnimationFromMode = ANIMATION_FROM_INIT;
+ theHudTextString = "No realtive from mode";
+ theUpdateHudTextFlag = true;
+ break;
+ }
+
+ case OSSIMPLANET_LOOKTO:
+ {
+ thePlanetManipulator->setEventHandlingFlag(true);
+ thePlanetManipulator->viewMatrixBuilder()->setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_Y);
+ theSimTime = 0.0;
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ theAnimationToMode = ANIMATION_TO_MODE_INIT;
+ theHudTextString = "Animation To Both Moving No Relative";
+ theUpdateHudTextFlag = true;
+
+ break;
+ }
+
+ case OSSIMPLANET_LOOKTO_DISPLACEMENT:
+ {
+
+ thePlanetManipulator->setEventHandlingFlag(true);
+ thePlanetManipulator->viewMatrixBuilder()->setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_Y);
+ theSimTime = 0.0;
+ theStartTick = osg::Timer::instance()->tick();
+ theLastAnimationModeTick = theStartTick;
+ double range = (viewer->model()->calculateUnnormalizedLength(thePointModel1->getBound().radius()))*10;
+
+ // setup Local LSR to calculate displacement
+ //
+ thePlanetManipulator->viewMatrixBuilder()->setLookFromNodeOffset(thePointModel1.get(),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ 0.0,
+ ossimPlanetViewMatrixBuilder::HEADING);
+
+ thePlanetManipulator->viewMatrixBuilder()->setLookToNode(thePointModel2.get());
+ thePlanetManipulator->viewMatrixBuilder()->setAttitudeHpr(osg::Vec3d(0.0,0.0, 0.0));
+ thePlanetManipulator->viewMatrixBuilder()->setLookToLocalDisplacement(osg::Vec3d(0.0,range*.1,-range*2));
+ theHudTextString = "Animation Look To displacement";
+ theUpdateHudTextFlag = true;
+
+ break;
+ }
+ case OSSIMPLANET_LOOKFROM_CONVERSION:
+ {
+ thePlanetManipulator->viewMatrixBuilder()->convertToAFromViewMatrix(false);
+ theHudTextString = "Converted to a look from without flatten";
+ theUpdateHudTextFlag = true;
+ break;
+ }
+ case OSSIMPLANET_LOOKFROM_CONVERSION_RANGE_FLATTEN:
+ {
+ //thePlanetManipulator->viewMatrixBuilder()->convertToAFromViewMatrix(true);
+ thePlanetManipulator->viewMatrixBuilder()->setParametersByMatrix(thePlanetManipulator->viewMatrixBuilder()->viewMatrix());
+ theHudTextString = "Converted to a look from with range flattened";
+ theUpdateHudTextFlag = true;
+ break;
+ }
+ case OSSIMPLANET_LOOKTO_ALONG_AXIS:
+ {
+ double range = (viewer->model()->calculateUnnormalizedLength(thePointModel1->getBound().radius()))*10;
+ osg::Vec3d from(thePointModel1->lsrSpace()->latLonAltitude());
+ osg::Vec3d to(thePointModel1->lsrSpace()->latLonAltitude());
+ from[2]+=range;
+ thePlanetManipulator->viewMatrixBuilder()->setLookFrom(from,
+ osg::Vec3d(0.0, 0.0, 0.0),
+ 0.0);
+ thePlanetManipulator->viewMatrixBuilder()->updateFromLocalDisplacement(osg::Vec3d(0.0,0.0,0.0));
+ thePlanetManipulator->viewMatrixBuilder()->setLookTo(to);
+ theHudTextString = "Looking down Z to a point";
+ theUpdateHudTextFlag = true;
+ break;
+ }
+ default:
+ break;
+ }
+
+}
+
+void TestHandler::initScene(ossimPlanetViewer* viewer)
+{
+ theFont = osgText::readFontFile(theFontName.c_str());
+ osg::ref_ptr<osg::Geode> geode = new osg::Geode();
+ osg::StateSet* stateset = geode->getOrCreateStateSet();
+ stateset->setMode(GL_LIGHTING,
+ osg::StateAttribute::OFF);
+ stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+ stateset->setRenderBinDetails(11,"RenderBin");
+ stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+ stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ stateset->setAttribute(new osg::PolygonMode(),
+ osg::StateAttribute::PROTECTED); // don't allow to go to wireframe
+ theHudCamera = new osg::CameraNode;
+ theHudViewport = new osg::Viewport(0,0,1024,1024);
+ theHudText = new osgText::Text;
+ theHudText->setSupportsDisplayList(false);
+ theHudText->setFont(theFont.get());
+ geode->addDrawable(theHudText.get());
+ theHudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ theHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(theHudViewport->x(),
+ theHudViewport->width(),
+ theHudViewport->y(),
+ theHudViewport->height()));
+ theHudCamera->setViewMatrix(osg::Matrix::identity());
+ theHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
+ theHudCamera->setRenderOrder(osg::CameraNode::POST_RENDER);
+ theHudCamera->addChild(geode.get());
+ osg::BoundingBox bb = osg::BoundingBox();
+ bb.expandBy(theHudText->getBound());
+ theHudText->setPosition(osg::Vec3d(5.0,bb.yMax()-bb.yMin(),0.0));
+}
+
+int main(int argc, char* argv[])
+{
+ ossimInit::instance()->initialize(argc, argv);
+
+ osg::ArgumentParser arguments(&argc,argv);
+ arguments.getApplicationUsage()->addCommandLineOption("--root-dir", "Root directory for testing");
+ //add more arguments
+
+ ossim_uint32 helpType = 0;
+
+ if ((helpType = arguments.readHelpType()))
+ {
+ arguments.getApplicationUsage()->write(std::cout, helpType);
+ return 1;
+ }
+
+ ossimString tempString;
+ osg::ArgumentParser::Parameter stringParam(tempString);
+
+ //Viewer and Test Handler Objects
+ osg::ref_ptr<ossimPlanetViewer> viewer = new ossimPlanetViewer(arguments); // object for viewer
+ osg::ref_ptr<TestHandler> testHandler = new TestHandler;
+ //osg::ref_ptr<ossimPlanetTerrain> terrain = new ossimPlanetTerrain();
+
+ //Event Handlers
+
+ viewer->addEventHandler(testHandler.get());
+ viewer->addEventHandler(new osgViewer::WindowSizeHandler);
+ viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
+ viewer->addEventHandler(new osgViewer::StatsHandler);
+
+ if(arguments.read("--root-dir", stringParam))
+ {
+ testHandler->setRootDirectory(ossimFilename(tempString));
+ }
+ while(!viewer->done())
+ {
+ viewer->frame(testHandler->simtime());
+ }
+
+ return 0;
+}
diff --git a/ossimPlanet/examples/ossimplanetviewer/GNUmakefile b/ossimPlanet/examples/ossimplanetviewer/GNUmakefile
new file mode 100644
index 0000000..d860c13
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/GNUmakefile
@@ -0,0 +1,21 @@
+TOPDIR = ../..
+include $(TOPDIR)/Make/makedefs
+
+CXXFILES =\
+ ossimplanetviewer.cpp \
+ opvLoadModel.cpp
+
+LIBS += $(OSSIM_LIBS) -lossimPlanet $(OSG_LIBS) $(OTHER_LIBS)
+
+ifeq ($(OS),Darwin)
+ LIBS += -bind_at_load
+endif
+
+INSTFILES = \
+ $(CXXFILES)\
+ GNUmakefile.inst=GNUmakefile
+LIB=
+EXEC = ossimplanetviewer
+
+include $(TOPDIR)/Make/makerules
+
diff --git a/ossimPlanet/examples/ossimplanetviewer/archive_manager.kwl b/ossimPlanet/examples/ossimplanetviewer/archive_manager.kwl
new file mode 100644
index 0000000..d0eb96b
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/archive_manager.kwl
@@ -0,0 +1,36 @@
+// Note: If you are specifying opacity values then the
+// bottom layer is not applied since it is just initially copied into the destination
+// All layers after that are blended based on the apacity. The default opacity is 255
+// which indicates completely opaque and anything less than that defines how
+// translucent the layer is.
+//
+// Note: You must name each layer archive0 upto archive<n-1> .
+// So currently if you delete a layer you must manually re-number
+// each keyword in the list.
+//
+// We support local and remote files. Currently for remote we only support
+// wms and you must give the full string for STYLES and layers you want and
+// make sure you end it with an &.
+//
+
+
+
+//archive0.type: local
+//archive0.file0: /data/earth/land_shallow_topo_east_tiled.tif
+//archive0.file1: /data/earth/land_shallow_topo_west_tiled.tif
+//archive0.transparent_color_flag:0
+//archive0.transparent_color: 0 0 0
+//archive0.opacity: 255
+
+//archive0.type: wms
+//archive0.server: http://neptune.flids.com/cgi-bin/ngos.cgi?LAYERS=Earth_Image,ngos
+//archive0.cache_dir: c:/data/wms/ngos/all
+
+//archive0.server: http://wmt.jpl.nasa.gov/cgi-bin/wmt.cgi?STYLES=visual&LAYERS=global_mosaic&sharp=0.0&
+
+archive0.type:wms
+archive0.server: http://wms.telascience.org/cgi-bin/bmng_wms_t?LAYERS=BMNG
+archive0.cache_dir: /data/wms/bmng
+archive0.opacity: 255
+
+
diff --git a/ossimPlanet/examples/ossimplanetviewer/opvLoadModel.cpp b/ossimPlanet/examples/ossimplanetviewer/opvLoadModel.cpp
new file mode 100644
index 0000000..d86abf9
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/opvLoadModel.cpp
@@ -0,0 +1,354 @@
+//
+// opvLoadModel.cpp
+//
+// osgPlanetView load model functionality
+//
+
+#include <osgDB/ReadFile>
+#include <osgUtil/SmoothingVisitor>
+
+#include <ossimPlanet/ossimPlanet.h>
+
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/base/ossimGeoidManager.h>
+#include <ossim/elevation/ossimElevManager.h>
+
+//
+// This visitor modifies each geometry it finds by creating
+// a transformArrayVisitor.
+//
+class geomVisitor : public osg::NodeVisitor
+{
+public:
+ geomVisitor()
+ :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
+ theMode(ossimPlanetLandType_NORMALIZED_ELLIPSOID)
+ {
+ }
+
+ virtual void apply(osg::Geode& node);
+ virtual void apply(osg::Node& node);
+ ossimPlanetLandType theMode;
+ osg::Vec3d theCenter;
+ ossimMapProjection* theProj;
+ ossimDpt theLocation;
+};
+
+//
+// This visitor modifies a vertex list by transforming each
+// vertex to ossimPlanet coordinates.
+//
+class transformArrayVisitor: public osg::ArrayVisitor
+{
+public:
+ transformArrayVisitor(ossimPlanetLandType mode=ossimPlanetLandType_NORMALIZED_ELLIPSOID):theMode(mode)
+ {
+ }
+ virtual void apply(osg::Vec3Array& array);
+
+ ossimPlanetLandType theMode;
+ osg::Vec3d theCenter;
+ ossimMapProjection* theProj;
+ ossimDpt theLocation;
+};
+
+void transformArrayVisitor::apply(osg::Vec3Array& array)
+{
+ unsigned int idx = 0;
+
+ switch(theMode)
+ {
+ case ossimPlanetLandType_NORMALIZED_ELLIPSOID:
+ {
+ ossimGpt gpt;
+ ossimEcefPoint ecef;
+ ecef = gpt;
+ double normalizationFactor = ecef.getMagnitude();
+ for(idx = 0; idx < array.size(); ++idx)
+ {
+ // Treat the coordinate of the model as meters
+ ossimDpt point(array[idx][0],
+ array[idx][1]);
+
+ // Offset to place the model at the desired UTM X,Y location
+ point += theLocation;
+
+ // Transform to geographic coordinates
+ theProj->eastingNorthingToWorld(point,
+ gpt);
+ double deltaH = ossimElevManager::instance()->getHeightAboveMSL(gpt);
+ if(ossim::isnan(deltaH))
+ {
+ deltaH = 0.0;
+ }
+ gpt.height(array[idx][2] +deltaH+ ossimGeoidManager::instance()->offsetFromEllipsoid(gpt));
+ // Transform to ossimPlanet coordinates
+ ecef = gpt;
+ array[idx][0] = ecef.x()/normalizationFactor;
+ array[idx][1] = ecef.y()/normalizationFactor;
+ array[idx][2] = ecef.z()/normalizationFactor;
+ }
+ break;
+ }
+ case ossimPlanetLandType_FLAT:
+ {
+ ossimGpt gpt;
+ ossimEcefPoint ecef;
+ for(idx = 0; idx < array.size(); ++idx)
+ {
+ theProj->eastingNorthingToWorld(ossimDpt(array[idx][0],
+ array[idx][1]),
+ gpt);
+ gpt.height(array[idx][2]);
+ array[idx][0] = gpt.lond();
+ array[idx][1] = gpt.latd();
+ array[idx][2] = gpt.height()/1000;
+ }
+ break;
+ }
+ default:
+ {
+ for(idx = 0; idx < array.size(); ++idx)
+ {
+ array[idx][0] -= theCenter[0];
+ array[idx][1] -= theCenter[1];
+ array[idx][2] -= theCenter[2];
+ }
+ break;
+ }
+ }
+}
+
+void geomVisitor::apply(osg::Geode& node)
+{
+ unsigned int drawableIdx = 0;
+
+ for(drawableIdx = 0; drawableIdx < node.getNumDrawables();++drawableIdx)
+ {
+ if(node.getDrawable(drawableIdx))
+ {
+ osg::Geometry* geomNode = node.getDrawable(drawableIdx)->asGeometry();
+
+ if(geomNode)
+ {
+ transformArrayVisitor visitor;
+ visitor.theProj = theProj;
+ visitor.theCenter = theCenter;
+ visitor.theLocation = theLocation;
+ visitor.theMode = theMode;
+ osg::Array* vertexArray = geomNode->getVertexArray();
+
+ vertexArray->accept(visitor);
+ geomNode->dirtyBound();
+ }
+ }
+ }
+
+ traverse(node);
+}
+
+void geomVisitor::apply(osg::Node& node)
+{
+ std::string name = node.getName();
+
+ if(name == "o1") // hack: remove the ground polygon so that only the city show up
+ {
+ osg::Group* group = node.asGroup();
+ if(group)
+ {
+ group->removeChild(0, group->getNumChildren());
+ }
+ }
+ osg::NodeVisitor::apply(node);
+}
+
+
+void transformPointsToLandType(osg::ref_ptr<osg::Node>& node,
+ const ossimFilename& /* file */ ,
+ ossimPlanetLandType landType,
+ int utmZone, int utmX, int utmY)
+{
+ geomVisitor visitor;
+ ossimRefPtr<ossimUtmProjection> proj = new ossimUtmProjection;
+ visitor.theMode = landType;
+ proj->setZone(utmZone);
+ visitor.theProj = proj.get();
+ visitor.theLocation.x = utmX;
+ visitor.theLocation.y = utmY;
+ node->accept(visitor);
+ node->dirtyBound();
+
+ osg::Vec3d v = node->getBound().center();
+ visitor.theMode = ossimPlanetLandType_NONE;
+ visitor.theCenter = v;
+ node->accept(visitor);
+ node->dirtyBound();
+ osg::MatrixTransform* mTransform = new osg::MatrixTransform;
+ osg::Matrixd localToWorld;
+ localToWorld.makeTranslate(v);
+ mTransform->setMatrix(localToWorld);
+ mTransform->addChild(node.get());
+// osgUtil::SmoothingVisitor smoother;
+// mTransform->accept(smoother);
+
+ node = mTransform;
+}
+
+/**
+ * Create a city by loading an OSG-supported 3D model file and
+ * transforming it onto the ossimPlanet ellipsoid.
+ *
+ * \param file Filename of the 3D model.
+ * \param landType Landtype of the ossimPlanet terrain.
+ * \param utmZone UTM Zone (from 1 to 60, or -1 to -60 for the
+ * southern hemisphere) in which to place the model.
+ * \param utmX X (easting) utm coordinate.
+ * \param utmY Y (northing) utm coordinate.
+ *
+ * \return The osg Node of the transformed model. Note that you
+ * will still need to add it to the scene graph with
+ * ossimPlanet::addChild()
+ */
+osg::ref_ptr<osg::Node> createCityModel(const ossimFilename& file,
+ ossimPlanetLandType landType,
+ int utmZone, int utmX, int utmY)
+{
+ osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(std::string(file.c_str()));
+
+ transformPointsToLandType(loadedModel, file, landType, utmZone, utmX, utmY);
+
+ return loadedModel;
+}
+
+
+#if 0
+//--------------------------------------------------------------------------------------------------
+class osgTestGroup : public osg::Group
+{
+public:
+ osgTestGroup(){}
+
+ virtual void traverse(osg::NodeVisitor& nv)
+ {
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ if((nv.getFrameStamp()->getFrameNumber()%5)==0)
+ {
+ nv.getDatabaseRequestHandler()->requestNodeFile("TEST",
+ this,
+ 99999999,
+ nv.getFrameStamp());
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ osg::Group::traverse(nv);
+ }
+ virtual bool addChild(osg::Node* node)
+ {
+ osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
+
+ if(geode)
+ {
+ if(getNumChildren() > 0)
+ {
+ removeChild(0, getNumChildren());
+ }
+ }
+ return osg::Group::addChild(node);
+ }
+};
+
+static int texCount = 0;
+class osgMyTexture : public osg::Texture2D
+{
+public:
+ osgMyTexture()
+ {
+ ++texCount;
+ std::cout << "Texture " << texCount << std::endl;
+ }
+ virtual ~osgMyTexture()
+ {
+ --texCount;
+ std::cout << "Texture " << texCount << std::endl;
+ }
+};
+class osgTestReaderWriter : public osgDB::ReaderWriter
+{
+public:
+ virtual ReadResult readNode(const std::string& fileName, const Options*)const
+ {
+ ReadResult result = 0;
+ if(fileName == "TEST")
+ {
+ std::cout << "Allocating geometry" << std::endl;
+ osg::ref_ptr<osg::Geode> geode = new osg::Geode;
+ osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
+
+ osg::ref_ptr<osg::Vec3Array> vArray = new osg::Vec3Array;
+ osg::ref_ptr<osg::Vec2Array> tArray = new osg::Vec2Array;
+ vArray->push_back(osg::Vec3d(-.5, .5,0.0));
+ vArray->push_back(osg::Vec3d(-.5, -.5, 0.0));
+ vArray->push_back(osg::Vec3d(.5, -.5, 0.0));
+ vArray->push_back(osg::Vec3d(.5, .5, 0.0));
+
+ tArray->push_back(osg::Vec2d(0.0,0.0));
+ tArray->push_back(osg::Vec2d(0,1.0));
+ tArray->push_back(osg::Vec2d(1.0,1.0));
+ tArray->push_back(osg::Vec2d(1.0,0.0));
+
+ osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D;
+// osg::ref_ptr<osg::Texture2D> tex = new osgMyTexture;
+ osg::ref_ptr<osg::Image> img = new osg::Image;
+ osg::ref_ptr<osg::StateSet> dstate = geom->getOrCreateStateSet();
+ unsigned char* newData = new unsigned char[256*256*4];
+ memset(newData, 255, 256*256*4);
+ img->setImage(256, 256, 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ newData,
+ osg::Image::USE_NEW_DELETE);
+
+ tex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
+ tex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
+ tex->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ tex->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ tex->setDataVariance(osg::Object::DYNAMIC);
+ tex->setImage(img.get());
+ osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
+ color->push_back(osg::Vec4(1.0,
+ 1.0,
+ 1.0,
+ 1.0));
+ geom->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geom->setColorArray(color.get());
+
+ dstate->setTextureAttributeAndModes(0, tex.get(),
+ osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
+
+ geom->setVertexArray(vArray.get());
+ geom->setTexCoordArray( 0, tArray.get());
+
+ osg::DrawArrays* drawArray = new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 1);
+ geom->addPrimitiveSet(drawArray);
+
+ geode->addDrawable(geom.get());
+ result = geode.get();
+ }
+ return result;
+ }
+};
+//-------------------------------------------------------------------------------------------------------------
+#endif
+
+
diff --git a/ossimPlanet/examples/ossimplanetviewer/opvLoadModel.h b/ossimPlanet/examples/ossimplanetviewer/opvLoadModel.h
new file mode 100644
index 0000000..861f28c
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/opvLoadModel.h
@@ -0,0 +1,9 @@
+//
+// opvLoadModel.h
+//
+// osgPlanetView load model functionality
+//
+
+osg::ref_ptr<osg::Node> createCityModel(const ossimFilename& file,
+ ossimPlanetLandType landType, int utmZone, int utmX, int utmY);
+
diff --git a/ossimPlanet/examples/ossimplanetviewer/ossimplanetviewer.cpp b/ossimPlanet/examples/ossimplanetviewer/ossimplanetviewer.cpp
new file mode 100644
index 0000000..9a616ea
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/ossimplanetviewer.cpp
@@ -0,0 +1,743 @@
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/init/ossimInit.h>
+#include <ossim/elevation/ossimElevManager.h>
+#include <iostream>
+#include <sstream>
+#include <osg/ArgumentParser>
+#include <osg/Texture>
+#include <osg/PositionAttitudeTransform>
+#include <osgDB/ReadFile>
+#include <osg/Drawable>
+#include <osg/io_utils>
+#include <time.h>
+#include <osgViewer/ViewerEventHandlers>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetManipulator.h>
+#include <ossimPlanet/ossimPlanetLatLonHud.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetTerrainGeometryTechnique.h>
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <ossimPlanet/ossimPlanetViewMatrixBuilder.h>
+#include <ossimPlanet/ossimPlanetCloudLayer.h>
+#include <ossimPlanet/ossimPlanetEphemeris.h>
+#include <osgGA/TrackballManipulator>
+#include <osgGA/FlightManipulator>
+#include <osgGA/DriveManipulator>
+#include <osgGA/KeySwitchMatrixManipulator>
+#include <osgGA/StateSetManipulator>
+#include <osgGA/AnimationPathManipulator>
+#include <osgGA/TerrainManipulator>
+#include <ossimPlanet/ossimPlanetAnimationPath.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <osg/Geometry>
+#include <osg/MatrixTransform>
+#include <osg/LineWidth>
+#include <osgText/Text>
+#include <osgUtil/CullVisitor>
+#include <osg/ClipPlane>
+
+#include <osg/Program>
+#include <osg/Uniform>
+
+#include <osg/Geode>
+#include <osg/Geometry>
+void setUpViewForMultipipeTest(ossimPlanetViewer& viewer, ossim_uint32 numberOfPipes)
+{
+ //unsigned int width = 640, height = 480, aspectRatio = 1.33;
+
+ osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
+ if (!wsi)
+ {
+ osg::notify(osg::NOTICE)<<"setUpViewForMultipipeTest() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
+ return;
+ }
+
+ osg::DisplaySettings* ds = osg::DisplaySettings::instance();
+ osg::GraphicsContext::ScreenIdentifier si;
+ si.readDISPLAY();
+ unsigned int screenWidth, screenHeight;
+ wsi->getScreenResolution(si, screenWidth, screenHeight);
+ ossim_float64 screenAspectRatio = (double)screenWidth/(double)screenHeight;
+ ossim_float64 targetWidth = screenWidth/numberOfPipes;
+ ossim_float64 targetHeight = screenHeight*.5;
+ ossim_float64 aspectRatio = targetWidth/targetHeight;//targetWidth/targetHeight;
+ // displayNum has not been set so reset it to 0.
+ if (si.displayNum<0) si.displayNum = 0;
+
+ double translate_x = 0.0;
+ for(unsigned int i=0; i<numberOfPipes; ++i)
+ {
+ translate_x += double(targetWidth) / (double(targetHeight) * aspectRatio);
+ }
+
+ for(unsigned int i=0; i<numberOfPipes; ++i)
+ {
+ osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
+ traits->hostName = si.hostName;
+ traits->displayNum = si.displayNum;
+ traits->screenNum = si.screenNum;
+ traits->x = i*targetWidth;
+ traits->y = 0;
+ traits->width = targetWidth;
+ traits->height = targetHeight;
+ traits->alpha = ds->getMinimumNumAlphaBits();
+ traits->stencil = ds->getMinimumNumStencilBits();
+ traits->windowDecoration = false;
+ traits->doubleBuffer = true;
+ traits->sharedContext = 0;
+ traits->sampleBuffers = ds->getMultiSamples();
+ traits->samples = ds->getNumMultiSamples();
+
+ osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
+
+ osg::ref_ptr<osg::Camera> camera = new osg::Camera;
+ camera->setGraphicsContext(gc.get());
+
+ osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
+ if (gw)
+ {
+ osg::notify(osg::INFO)<<" GraphicsWindow has been created successfully."<<gw<<std::endl;
+
+ gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(traits->x, traits->y, traits->width, traits->height );
+ }
+ else
+ {
+ osg::notify(osg::NOTICE)<<" GraphicsWindow has not been created successfully."<<std::endl;
+ }
+
+ camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
+
+ GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
+ camera->setDrawBuffer(buffer);
+ camera->setReadBuffer(buffer);
+#if 0
+ if(i==0)
+ {
+ // we will set a predraw callback here because the master camera is loosing the callback for some reason
+ //
+ camera->setPreDrawCallback(new ossimPlanetViewer::DrawCallback(&viewer));
+ }
+#endif
+ double newAspectRatio = double(traits->width) / double(traits->height);
+ double aspectRatioChange = newAspectRatio / aspectRatio;
+ //double aspectRatioChange = newAspectRatio / screenAspectRatio;
+
+// viewer.addSlave(camera.get(),
+// (osg::Matrixd::translate( translate_x - aspectRatioChange, 0.0, 0.0) *
+// osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0)),
+// osg::Matrixd(), true );
+ viewer.addSlave(camera.get(),
+ (osg::Matrixd::translate( translate_x - aspectRatioChange, 0.0, 0.0) *
+ osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0)),
+ osg::Matrixd(), true );
+ translate_x -= aspectRatioChange * 2.0;
+ }
+ viewer.assignSceneDataToCameras();
+}
+osg::Node* loadFlightGearModel(ossimFilename& file,
+ ossimPlanetGeoRefModel* model)
+{
+ osg::MatrixTransform* orientedModel = new osg::MatrixTransform;
+ osg::Node* flightgearModel = osgDB::readNodeFile(file.c_str(), 0);
+ osg::Matrixd mr;
+ osg::Matrixd ms;
+ double scale = 50.0/model->getNormalizationScale();
+ ms.makeScale(osg::Vec3d(scale, scale, scale));
+ mr.makeRotate(osg::DegreesToRadians(-90.0), osg::Vec3d(0.0,0.0,1.0),
+ osg::DegreesToRadians(-90.0), osg::Vec3d(0.0,1.0,0.0),
+ osg::DegreesToRadians(0.0), osg::Vec3d(1.0,0.0,0.0));
+ orientedModel->setMatrix(ms*mr);
+ if(flightgearModel)
+ {
+ orientedModel->addChild(flightgearModel);
+ }
+ // orientedModel->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
+ return orientedModel;
+}
+
+void test(ossimPlanetGeoRefModel* model)
+{
+ osg::ref_ptr<ossimPlanetViewMatrixBuilder> builder = new ossimPlanetViewMatrixBuilder(model);
+ osg::Vec3d llh, hpr;
+ builder->setLookFrom(osg::Vec3d(45, -28, 3000),
+ osg::Vec3d(45,45,0.0),
+ 0.0);
+
+ osg::ref_ptr<ossimPlanetViewMatrixBuilder> builder2 = new ossimPlanetViewMatrixBuilder(builder->viewMatrix(),
+ model);
+
+ builder->extractCompositedLlhHprParameters(llh, hpr);
+ std::cout << "llh: " << llh << "\n" << "hpr: " << hpr << std::endl;
+
+}
+
+void testHprInvert()
+{
+ osg::ref_ptr<ossimPlanetViewMatrixBuilder> builder = new ossimPlanetViewMatrixBuilder;
+
+ builder->setGeoRefModel(new ossimPlanetNormalizedEllipsoidModel());
+ builder->setLookFrom(osg::Vec3d(56.7725, -3.84375, 6224.26),
+ osg::Vec3d(-7.69345, -10.4819, 0.0),
+ 0.0);
+ builder->setLookTo(osg::Vec3d(57.0337, -3.90847, 860.493));
+
+ osg::Matrix targetOrientation = builder->viewMatrix();
+ osg::Vec3d targetXaxis(targetOrientation(0,0), targetOrientation(0,1), targetOrientation(0,2));
+ osg::Vec3d targetYaxis(targetOrientation(1,0), targetOrientation(1,1), targetOrientation(1,2));
+ osg::Vec3d targetZaxis(targetOrientation(2,0), targetOrientation(2,1), targetOrientation(2,2));
+ builder->setParametersByMatrix(builder->viewMatrix());
+ //builder->convertToAFromViewMatrix();
+ //builder->convertToAFromViewMatrix(true);
+
+ osg::Matrix tempM= builder->viewMatrix();
+
+ osg::Vec3d xAxis(tempM(0,0), tempM(0,1), tempM(0,2));
+ osg::Vec3d yAxis(tempM(1,0), tempM(1,1), tempM(1,2));
+ osg::Vec3d zAxis(tempM(2,0), tempM(2,1), tempM(2,2));
+
+ std::cout << "Result X = " << xAxis*targetXaxis << std::endl;
+ std::cout << "Result Y = " << yAxis*targetYaxis << std::endl;
+ std::cout << "Result Z = " << zAxis*targetZaxis << std::endl;
+
+
+ std::cout << builder->fromPositionLlh() << std::endl;
+ std::cout << builder->fromHpr() << std::endl;
+ std::cout << builder->fromRange() << std::endl;
+}
+int main(int argc, char* argv[])
+{
+ ossimInit::instance()->initialize(argc, argv);
+
+// testHprInvert();
+// return 0;
+ osg::ref_ptr<ossimPlanetGrid> grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_CAP);
+
+ ossimString tempString;
+ osg::ArgumentParser::Parameter stringParam(tempString);
+
+ osg::ArgumentParser arguments(&argc,argv);
+ arguments.getApplicationUsage()->addCommandLineOption("--terrain-requests-per-frame",
+ "Specify the number of requests to apply to the terrain graph per frame");
+ arguments.getApplicationUsage()->addCommandLineOption("--terrain-threads",
+ "Specify the number of terrain threads to use Specify between 1 and 3 for now");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-image", "Image to add");
+ arguments.getApplicationUsage()->addCommandLineOption("--polar-cap", "Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--osg-view", "no ossimPlanet just use osg's readNode to add to scene");
+ arguments.getApplicationUsage()->addCommandLineOption("--split-merge-speed", "enumeration that maps to split merge ratio. Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, and HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--elevation-density-type", "enumeration that maps amount of elevation posts to use per patch. Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, and HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--texture-density-type", "enumeration that maps amount of texture samples to use per patch. Values can be LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, and HIGH");
+ arguments.getApplicationUsage()->addCommandLineOption("--elevation-exaggeration", "Scales the elevation by this factor");
+ arguments.getApplicationUsage()->addCommandLineOption("--cull-amount", "Sets the amount of culling in the graph. Values can be low, medium, high");
+ arguments.getApplicationUsage()->addCommandLineOption("--min-time-compile", "sets the minimum time to compile per frame in seconds. So 3 milliseconds is .003");
+ arguments.getApplicationUsage()->addCommandLineOption("--animation-path", "Reads in an animation path");
+ arguments.getApplicationUsage()->addCommandLineOption("--animation-node", "Reads in an animation node");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-kml", "Adds a kml layer to planet");
+ arguments.getApplicationUsage()->addCommandLineOption("--moon-image", "Moon image used for the moon sprite for the Ephemeris");
+ arguments.getApplicationUsage()->addCommandLineOption("--sun-image", "Moon image used for the moon sprite for the Ephemeris");
+ arguments.getApplicationUsage()->addCommandLineOption("--visibility", "Visibility in meters");
+ arguments.getApplicationUsage()->addCommandLineOption("--fog-near", "near plane for fog attenuation in meters");
+ arguments.getApplicationUsage()->addCommandLineOption("--cloud-coverage", "integer value used to adjust the perlin noise");
+ arguments.getApplicationUsage()->addCommandLineOption("--cloud-sharpness", "float value (0..1) used to adjust the perlin noise");
+ arguments.getApplicationUsage()->addCommandLineOption("--cloud-altitude", "Altitude of the cloud");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-cloud", "float value (0..1) used to adjust the perlin noise");
+ arguments.getApplicationUsage()->addCommandLineOption("--fog-near", "near plane for fog attenuation in meters");
+ arguments.getApplicationUsage()->addCommandLineOption("--time-scale", "time scale for animation path locking");
+ arguments.getApplicationUsage()->addCommandLineOption("--time-offset", "time offset");
+ arguments.getApplicationUsage()->addCommandLineOption("--lockview-path", "lock the view to the path");
+ arguments.getApplicationUsage()->addCommandLineOption("--add-ephemeris", "Adds the ephemeris defaults");
+
+
+
+ ossim_uint32 helpType = 0;
+
+ if ((helpType = arguments.readHelpType()))
+ {
+ arguments.getApplicationUsage()->write(std::cout, helpType);
+ return 1;
+ }
+
+#if 1
+
+ osg::MatrixTransform* rootScene = new osg::MatrixTransform();
+
+ // osg::DisplaySettings::instance()->setRGB(true);
+ // osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts(1);
+ ossimPlanetTerrainGeometryTechnique* technique = new ossimPlanetTerrainGeometryTechnique();
+ ossimPlanetViewer viewer(arguments);
+ ossimPlanetTerrain::CullAmountType cullAmount = ossimPlanetTerrain::HIGH_CULL;
+ ossimPlanetTerrain::SplitMergeSpeedType splitMergeSpeed = ossimPlanetTerrain::LOW_SPEED;
+ ossimPlanetTerrain::ElevationDensityType elevationDensity = ossimPlanetTerrain::LOW_ELEVATION_DENSITY;
+ ossimPlanetTerrain::TextureDensityType textureDensity = ossimPlanetTerrain::MEDIUM_TEXTURE_DENSITY;
+ std::vector<osg::ref_ptr<ossimPlanetAnimationPath> > animationPathArray;
+ std::vector<osg::ref_ptr<ossimPlanetPointModel> > pointModels;
+ std::vector<osg::ref_ptr<ossimPlanetAnimatedPointModel> > animatedPointModels;
+ osg::ref_ptr<ossimPlanetGeoRefModel> model;
+ osg::ref_ptr<ossimPlanetManipulator> manipulator = new ossimPlanetManipulator();
+ osg::ref_ptr<ossimPlanetAnnotationLayer> annotationLayer =new ossimPlanetAnnotationLayer();
+ osg::ref_ptr<ossimPlanetKmlLayer> kmlLayer;
+ std::vector<ossimFilename> kmlFiles;
+ ossimFilename flightgearFile = "";
+ osg::ref_ptr<ossimPlanet> planet;
+ double elevationExaggeration = 1.0;
+ double minTimeToCompilePerFrame = .003;
+ ossimFilename sunTextureFile = "";
+ ossimFilename moonTextureFile = "";
+ ossim_float64 visibility = 1000000000.0;
+ ossim_float64 fogNear = 0.0;
+ ossim_int32 cloudCoverage = 20;
+ ossim_float64 cloudSharpness = .95;
+ ossim_float64 cloudAltitude = 20000;
+ double timeScale = 1.0;
+ double timeOffset = 0.0;
+ bool addCloud = false;
+ bool lockViewToPathFlag = false;
+ bool addEphemerisFlag = false;
+ if(arguments.read("--lockview-path", stringParam))
+ {
+ lockViewToPathFlag =tempString.toBool();
+ }
+ if(arguments.read("--time-scale", stringParam))
+ {
+ timeScale = tempString.toDouble();
+ }
+ if(arguments.read("--time-offset", stringParam))
+ {
+ timeOffset = tempString.toDouble();
+ }
+ if(arguments.read("--cloud-coverage", stringParam))
+ {
+ cloudCoverage = tempString.toDouble();
+ }
+ if(arguments.read("--cloud-sharpness", stringParam))
+ {
+ cloudSharpness = tempString.toDouble();
+ }
+ if(arguments.read("--cloud-altitude", stringParam))
+ {
+ cloudAltitude = tempString.toDouble();
+ }
+ if(arguments.read("--add-ephemeris"))
+ {
+ addEphemerisFlag = true;
+ }
+ if(arguments.read("--add-cloud"))
+ {
+ addCloud = true;
+ }
+ if(arguments.read("--visibility", stringParam))
+ {
+ visibility = tempString.toDouble();
+ }
+ if(arguments.read("--fog-near", stringParam))
+ {
+ fogNear = tempString.toDouble();
+ }
+ while(arguments.read("--add-kml", stringParam))
+ {
+ kmlFiles.push_back(ossimFilename(tempString));
+ }
+ if(arguments.read("--animation-node", stringParam))
+ {
+ flightgearFile = ossimFilename(tempString);
+ }
+ while(arguments.read("--animation-path", stringParam))
+ {
+ osg::ref_ptr<ossimPlanetAnimationPath> animationPath = new ossimPlanetAnimationPath;
+
+ if(animationPath->openAnimationPathByXmlDocument(ossimFilename(tempString)))
+ {
+ animationPathArray.push_back(animationPath.get());
+ }
+ }
+ if(arguments.read("--moon-image", stringParam))
+ {
+ moonTextureFile = ossimFilename(tempString);
+ }
+ if(arguments.read("--sun-image", stringParam))
+ {
+ sunTextureFile = ossimFilename(tempString);
+ }
+ if(arguments.read("--min-time-compile", stringParam))
+ {
+ minTimeToCompilePerFrame = tempString.toDouble();
+ }
+ if(arguments.read("--elevation-exaggeration", stringParam))
+ {
+ elevationExaggeration = tempString.toDouble();
+ }
+ if(arguments.read("--texture-density-type", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ textureDensity = ossimPlanetTerrain::LOW_TEXTURE_DENSITY;
+ }
+ else if(tempString == "medium_low")
+ {
+ textureDensity = ossimPlanetTerrain::MEDIUM_LOW_TEXTURE_DENSITY;
+ }
+ else if(tempString == "medium")
+ {
+ textureDensity = ossimPlanetTerrain::MEDIUM_TEXTURE_DENSITY;
+ }
+ else if(tempString == "medium_high")
+ {
+ textureDensity = ossimPlanetTerrain::MEDIUM_HIGH_TEXTURE_DENSITY;
+ }
+ else if(tempString == "high")
+ {
+ textureDensity = ossimPlanetTerrain::HIGH_TEXTURE_DENSITY;
+ }
+ }
+ if(arguments.read("--elevation-density-type", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ elevationDensity = ossimPlanetTerrain::LOW_ELEVATION_DENSITY;
+ }
+ else if(tempString == "medium_low")
+ {
+ elevationDensity = ossimPlanetTerrain::MEDIUM_LOW_ELEVATION_DENSITY;
+ }
+ else if(tempString == "medium")
+ {
+ elevationDensity = ossimPlanetTerrain::MEDIUM_ELEVATION_DENSITY;
+ }
+ else if(tempString == "medium_high")
+ {
+ elevationDensity = ossimPlanetTerrain::MEDIUM_HIGH_ELEVATION_DENSITY;
+ }
+ else if(tempString == "high")
+ {
+ elevationDensity = ossimPlanetTerrain::HIGH_ELEVATION_DENSITY;
+ }
+ }
+ if(arguments.read("--split-merge-speed", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::LOW_SPEED;
+ }
+
+ else if(tempString == "medium_low")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::MEDIUM_LOW_SPEED;
+ }
+ else if(tempString == "medium")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::MEDIUM_SPEED;
+ }
+ else if(tempString == "medium_high")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::MEDIUM_HIGH_SPEED;
+ }
+ else if(tempString == "high")
+ {
+ splitMergeSpeed = ossimPlanetTerrain::HIGH_SPEED;
+ }
+ }
+ if(arguments.read("--polar-cap", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "low")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::LOW_CAP);
+ }
+ else if(tempString == "medium_low")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_LOW_CAP);
+ }
+ else if(tempString == "medium")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_CAP);
+ }
+ else if(tempString == "medium_high")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::MEDIUM_HIGH_CAP);
+ }
+ else if(tempString == "high")
+ {
+ grid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::HIGH_CAP);
+ }
+ }
+ if(arguments.read("--cull-amount", stringParam))
+ {
+ tempString = tempString.downcase();
+ if(tempString == "none")
+ {
+ cullAmount = ossimPlanetTerrain::NO_CULL;
+ }
+ if(tempString == "low")
+ {
+ cullAmount = ossimPlanetTerrain::LOW_CULL;
+ }
+ else if(tempString == "medium_low")
+ {
+ cullAmount = ossimPlanetTerrain::MEDIUM_LOW_CULL;
+ }
+ else if(tempString == "medium")
+ {
+ cullAmount = ossimPlanetTerrain::MEDIUM_CULL;
+ }
+ else if(tempString == "medium_high")
+ {
+ cullAmount = ossimPlanetTerrain::MEDIUM_HIGH_CULL;
+ }
+ else if(tempString == "high")
+ {
+ cullAmount = ossimPlanetTerrain::HIGH_CULL;
+ }
+ }
+
+ viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
+
+ // add the thread model handler
+ viewer.addEventHandler(new osgViewer::ThreadingHandler);
+
+ // add the window size toggle handler
+ viewer.addEventHandler(new osgViewer::WindowSizeHandler);
+
+ // add the stats handler
+ viewer.addEventHandler(new osgViewer::StatsHandler);
+
+ // add the help handler
+ viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
+
+ // add the record camera path handler
+ viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
+
+ // add the LOD Scale handler
+ // viewer.addEventHandler(new osgViewer::LODScaleHandler);
+
+ // add the screen capture handler
+ // viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
+ osg::ref_ptr<osg::Node> lockNode;
+ if(arguments.read("--osg-view", stringParam))
+ {
+ osg::ref_ptr<osg::Node> n = osgDB::readNodeFile(tempString);
+ if(n.valid())
+ {
+ osg::Group* group = new osg::Group();
+ group->addChild(n.get());
+ viewer.setSceneData(group);
+ }
+ osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
+ keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
+ keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
+ keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
+ keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
+ viewer.setCameraManipulator(keyswitchManipulator.get());
+ viewer.realize();
+
+ while(!viewer.done())
+ {
+ viewer.frame();//time);
+ }
+
+ return 0;
+ }
+ else
+ {
+ planet = new ossimPlanet();
+// osg::ref_ptr<ossimPlanetLatLonHud> latLonHud = new ossimPlanetLatLonHud;
+ model = planet->model().get();
+ osg::ref_ptr<ossimPlanetTerrain> terrain = new ossimPlanetTerrain(grid.get());
+ terrain->setTerrainTechnique(technique);
+ terrain->setCullAmountType(cullAmount);
+ terrain->setSplitMergeSpeedType(splitMergeSpeed);
+ terrain->setTextureDensityType(textureDensity);
+ terrain->setElevationDensityType(elevationDensity);
+ terrain->setElevationExaggeration(elevationExaggeration);
+ terrain->setMinimumTimeToCompilePerFrameInSeconds(minTimeToCompilePerFrame);
+ //terrain->setTextureLayer(0, group);
+ terrain->initElevation();
+ planet->addChild(terrain.get());
+ planet->addChild(annotationLayer.get());
+// planet->addChild(latLonHud.get());
+
+ // ossimPlanetEphemeris* ephemeris = new ossimPlanetEphemeris(ossimPlanetEphemeris::SUN_LIGHT);//|
+ //ossimPlanetEphemeris::MOON_LIGHT);
+ //planet->addChild(ephemeris);
+ if(kmlFiles.size() > 0)
+ {
+ kmlLayer = new ossimPlanetKmlLayer();
+ planet->addChild(kmlLayer.get());
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < kmlFiles.size(); ++idx)
+ {
+ kmlLayer->addKml(kmlFiles[idx]);
+ }
+ }
+ if(!flightgearFile.empty())
+ {
+ osg::ref_ptr<osg::Node> flightgearNode = loadFlightGearModel(flightgearFile,
+ planet->model().get());
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < animationPathArray.size(); ++idx)
+ {
+ osg::ref_ptr<ossimPlanetAnimatedPointModel> animatedNode = new ossimPlanetAnimatedPointModel();
+ osg::ref_ptr<ossimPlanetPointModel> pointModel = new ossimPlanetPointModel;
+ pointModel->setCullingActive(false);
+ pointModel->setNode(flightgearNode.get());
+ animationPathArray[idx]->setLoopMode(osg::AnimationPath::LOOP);
+ animatedNode->setPointModel(pointModel.get());
+ animatedNode->setAnimationPath(animationPathArray[idx].get());
+ animatedNode->setTimeScale(timeScale);
+ animatedNode->setTimeOffset(timeOffset);
+ animatedNode->setShowModelFlag(true);
+ annotationLayer->addChild(animatedNode.get());
+ pointModels.push_back(pointModel.get());
+ animatedPointModels.push_back(animatedNode.get());
+ if(lockViewToPathFlag)
+ {
+ lockNode = pointModel.get();
+ }
+ }
+ }
+ else if(!animationPathArray.empty()){
+ osg::ref_ptr<ossimPlanetAnimatedPointModel> animatedNode = new ossimPlanetAnimatedPointModel();
+ osg::ref_ptr<ossimPlanetPointModel> pointModel = new ossimPlanetPointModel;
+ pointModel->setCullingActive(false);
+ animationPathArray[0]->setLoopMode(osg::AnimationPath::LOOP);
+ animatedNode->setPointModel(pointModel.get());
+ animatedNode->setAnimationPath(animationPathArray[0].get());
+ animatedNode->setTimeScale(timeScale);
+ animatedNode->setTimeOffset(timeOffset);
+ animatedNode->setShowModelFlag(false);
+ annotationLayer->addChild(animatedNode.get());
+ pointModels.push_back(pointModel.get());
+ animatedPointModels.push_back(animatedNode.get());
+ if(lockViewToPathFlag)
+ {
+ lockNode = pointModel.get();
+ }
+ }
+ rootScene->addChild(planet.get());
+ viewer.setSceneData( rootScene );
+
+ osg::ref_ptr<osg::StateSet> sset = planet->getOrCreateStateSet();
+ if(arguments.read("--terrain-requests-per-frame", stringParam))
+ {
+ ossim_int32 requestsPerFrame = ossimString(tempString).toInt32();
+ if(requestsPerFrame <= 0)
+ {
+ requestsPerFrame = 1;
+ }
+ viewer.setTerrainMaxNumberOfOperationsToApplyToGraphPerFrame(requestsPerFrame);
+ }
+ while(arguments.read("--add-image", stringParam))
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(tempString);
+ if(layer.valid())
+ {
+ viewer.addImageTexture(layer.get());
+
+ }
+ }
+ osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
+ keyswitchManipulator->addMatrixManipulator( '1', "Standard", manipulator.get() );
+ keyswitchManipulator->addMatrixManipulator( '2', "Trackball", new osgGA::TrackballManipulator() );
+ keyswitchManipulator->addMatrixManipulator( '3', "Flight", new osgGA::FlightManipulator() );
+ keyswitchManipulator->addMatrixManipulator( '4', "Drive", new osgGA::DriveManipulator() );
+ keyswitchManipulator->addMatrixManipulator( '5', "Terrain", new osgGA::TerrainManipulator() );
+ viewer.setCameraManipulator(keyswitchManipulator.get());
+ }
+ // test(planet->model().get());
+ // return 0;
+ viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
+
+if(addEphemerisFlag)
+{
+
+ viewer.addEphemeris(ossimPlanetEphemeris::SUN_LIGHT
+ //|ossimPlanetEphemeris::MOON_LIGHT
+ //|ossimPlanetEphemeris::AMBIENT_LIGHT
+ // |ossimPlanetEphemeris::SUN
+ |ossimPlanetEphemeris::MOON
+ |ossimPlanetEphemeris::SKY
+ |ossimPlanetEphemeris::FOG
+ );
+ ossimLocalTm date;
+ date.now();
+ viewer.ephemeris()->setDate(date);
+ //viewer.ephemeris()->setApplySimulationTimeOffsetFlag(true);
+ viewer.ephemeris()->setApplySimulationTimeOffsetFlag(true);
+ viewer.ephemeris()->setSunTextureFromFile(sunTextureFile);
+ viewer.ephemeris()->setMoonTextureFromFile(moonTextureFile);
+ viewer.ephemeris()->setMoonScale(osg::Vec3d(1.0, 1.0, 1.0));
+// viewer.ephemeris()->setGlobalAmbientLight(osg::Vec3d(0.1, 0.1, 0.1));
+ viewer.ephemeris()->setVisibility(visibility);
+ viewer.ephemeris()->setFogNear(fogNear);
+ viewer.ephemeris()->setFogMode(ossimPlanetEphemeris::LINEAR);
+ //viewer.ephemeris()->setSunLightCallback(new ossimPlanetEphemeris::LightingCallback());
+ double fov_y, aspect_ratio, z_near, z_far;
+ viewer.getCamera()->getProjectionMatrixAsPerspective(fov_y, aspect_ratio, z_near, z_far);
+ viewer.getCamera()->setProjectionMatrixAsPerspective(45, aspect_ratio, 1.0, 20.0);
+ //osg::ref_ptr<ossimPlanetCloudLayer> cloud;
+ if(addCloud)
+ {
+// viewer.ephemeris()->setNumberOfCloudLayers(1);
+#if 0
+ viewer.ephemeris()->createCloudPatch(0,
+ osg::Vec3d(28, -90, cloudAltitude),
+ 64,
+ 45,
+ (ossim_uint64)time(0),
+ cloudCoverage,
+ cloudSharpness);
+ // viewer.ephemeris()->cloudLayer(0)->setMaxAltitudeToShowClouds(cloudAltitude*2.0);
+#else
+ // viewer.ephemeris()->cloudLayer(0)->setGrid(new ossimPlanetCloudLayer::Patch(45.0, 45.0));
+ viewer.ephemeris()->setNumberOfCloudLayers(1);
+ viewer.ephemeris()->cloudLayer(0)->computeMesh(cloudAltitude, 128, 128, 0);
+ viewer.ephemeris()->cloudLayer(0)->updateTexture(time(0), cloudCoverage, cloudSharpness);
+ viewer.ephemeris()->cloudLayer(0)->setSpeedPerHour(1000, OSSIM_MILES);
+ viewer.ephemeris()->cloudLayer(0)->setScale(3);
+ viewer.ephemeris()->cloudLayer(0)->setMaxAltitudeToShowClouds(cloudAltitude*2.0);
+#endif
+ }
+ viewer.terrainLayer()->setElevationMemoryCache(new ossimPlanetMemoryImageCache);
+ viewer.terrainLayer()->elevationCache()->setMinMaxCacheSizeInMegaBytes(16, 20);
+}
+ if(arguments.read("--multi-pipe-test", stringParam))
+ {
+ setUpViewForMultipipeTest(viewer, tempString.toUInt32());
+ }
+ viewer.realize();
+
+ // viewer.setLightingMode(osg::View::HEADLIGHT);
+ // if(viewer.getLight())
+ // {
+ // osg::Vec4f amb(.3,.3,.3,1.0);
+ // viewer.getLight()->setAmbient(amb);
+ // }
+
+ // osg::ref_ptr<ossimPlanetViewMatrixBuilder> viewMatrixBuilder;
+ // if(planet.valid())
+ // {
+ // viewMatrixBuilder = new ossimPlanetViewMatrixBuilder(planet->model().get());
+ // }
+
+ //animatedNode->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ //viewer.setCameraManipulator(0);
+ double time = 0.0;
+ manipulator->setEventHandlingFlag(true);
+ manipulator->viewMatrixBuilder()->setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_Y);
+ if(lockNode.get())
+ {
+ manipulator->viewMatrixBuilder()->updateFromNode(lockNode.get());
+ }
+ while(!viewer.done())
+ {
+ viewer.frame();//time);
+ time += 1.0/60.0;//60;//.016;
+ }
+ //return viewer.run();
+#endif
+}
diff --git a/ossimPlanet/examples/ossimplanetviewer/ossimplanetviewer.vcproj b/ossimPlanet/examples/ossimplanetviewer/ossimplanetviewer.vcproj
new file mode 100644
index 0000000..93b5627
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/ossimplanetviewer.vcproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="ossimplanetviewer"
+ ProjectGUID="{982CDBCD-0217-4E0D-8870-338D101EB982}"
+ RootNamespace="ossimplanetviewer"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\..\ossim_dependencies\src\3rdParty\include";"$(ProjectDir)..\..\..\ossim\include";"$(ProjectDir)..\..\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\zziplib-0.13.49";"$(ProjectDir)..\..\..\libwms\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph\include""
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CONSOLE;OSGPLANET_WITHOUT_WMS;FREETYPE_SETTING=1;GEOTIFF_ENABLED;HAVE_CONFIG_H"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(SolutionDir)bin\ossimplanetviewer.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="C:\Svs_dev_C\ossim\lib;C:\Svs_dev_C\3rdParty\lib;C:\Svs_dev_C\OpenThreads\lib\win32;C:\Svs_dev_C\Producer\lib;C:\Svs_dev_C\OpenSceneGraph\lib;C:\Svs_dev_C\gdal"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/ossimplanetviewer.pdb"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\include";"$(ProjectDir)..\..\..\ossim\include";"$(ProjectDir)..\..\..\libwms\include";"$(ProjectDir)..\..\..\ossim_dependencies\include""
+ PreprocessorDefinitions="NDEBUG;_WINDOWS;WIN32;_CONSOLE;NOMINMAX"
+ RuntimeLibrary="2"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="OpenThreads.lib osg.lib osgDB.lib osgViewer.lib osgGA.lib osgText.lib osgUtil.lib"
+ OutputFile="$(OutDir)\bin\$(ProjectName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""$(ProjectDir)..\..\..\ossim\projects\vs2005\bin\Release";"$(ProjectDir)..\..\..\ossim_dependencies\lib";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph-2.8.1\build\lib""
+ GenerateDebugInformation="false"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)\lib\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\opvLoadModel.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ossimplanetviewer.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\opvLoadModel.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/ossimPlanet/examples/ossimplanetviewer/readme.txt b/ossimPlanet/examples/ossimplanetviewer/readme.txt
new file mode 100644
index 0000000..200039a
--- /dev/null
+++ b/ossimPlanet/examples/ossimplanetviewer/readme.txt
@@ -0,0 +1,9 @@
+The osgplanetviewer now only accepts a keywordlist. See archive_manager.kwl for the sample format. You will have to modify the cache_dir. See the comments in archive_manager.kwl
+
+example:
+
+osgplanetviewer archive_manager.kwl
+
+
+
+
diff --git a/ossimPlanet/include/ossimPlanet/compiler.h b/ossimPlanet/include/ossimPlanet/compiler.h
new file mode 100644
index 0000000..5d5534d
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/compiler.h
@@ -0,0 +1,470 @@
+/**************************************************************************
+ * compiler.h -- C++ Compiler Portability Macros
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id: compiler.h 10524 2007-02-26 18:27:24Z gpotts $
+ *
+ **************************************************************************/
+
+/** \file compiler.h
+ * A set of defines to encapsulate compiler and platform differences.
+ * Please refer to the source code for full documentation on this file.
+ *
+ * Here is a summary of what this file does.
+ *
+ * (1) Defines macros for some STL includes which may be affected
+ * by file name length limitations.
+ *
+ * (2) Defines macros for some features not supported by all C++ compilers.
+ *
+ * (3) Defines 'explicit' as a null macro if the compiler doesn't support
+ * the explicit keyword.
+ *
+ * (4) Defines 'typename' as a null macro if the compiler doesn't support
+ * the typename keyword.
+ *
+ * (5) Defines bool, true and false if the compiler doesn't do so.
+ *
+ * (6) Defines SG_EXPLICIT_FUNCTION_TMPL_ARGS if the compiler
+ * supports calling a function template by providing its template
+ * arguments explicitly.
+ *
+ * (7) Defines SG_NEED_AUTO_PTR if STL doesn't provide auto_ptr<>.
+ *
+ * (8) Defines SG_NO_ARROW_OPERATOR if the compiler is unable
+ * to support operator->() for iterators.
+ *
+ * (9) Defines SG_USE_EXCEPTIONS if the compiler supports exceptions.
+ * Note: no FlightGear code uses exceptions.
+ *
+ * (10) Define SG_NAMESPACES if the compiler supports namespaces.
+ *
+ * (11) SG_MATH_FN_IN_NAMESPACE_STD -- not used??
+ *
+ * (12) Define SG_HAVE_STD if std namespace is supported.
+ *
+ * (13) Defines SG_CLASS_PARTIAL_SPECIALIZATION if the compiler
+ * supports partial specialization of class templates.
+ *
+ * (14) Defines SG_HAVE_STD_INCLUDES to use ISO C++ Standard headers.
+ *
+ * (15) Defines SG_HAVE_STREAMBUF if <streambuf> of <streambuf.h> are present.
+ *
+ * (16) Define SG_MATH_EXCEPTION_CLASH if math.h defines an exception class
+ * that clashes with the one defined in <stdexcept>.
+ */
+
+#ifndef _SG_COMPILER_H
+#define _SG_COMPILER_H
+
+/*
+ * Helper macro SG_STRINGIZE:
+ * Converts the parameter X to a string after macro replacement
+ * on X has been performed.
+ */
+#define SG_STRINGIZE(X) SG_DO_STRINGIZE(X)
+#define SG_DO_STRINGIZE(X) #X
+
+#ifdef __GNUC__
+# if __GNUC__ == 2
+# if __GNUC_MINOR__ < 8
+
+ // g++-2.7.x
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip.h>
+# define STL_IOSTREAM <iostream.h>
+# define STL_ITERATOR <iterator.h>
+# define STL_FSTREAM <fstream.h>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+# define STL_STRSTREAM <strstream.h>
+
+# define SG_NEED_AUTO_PTR
+# define SG_NO_DEFAULT_TEMPLATE_ARGS
+# define SG_INCOMPLETE_FUNCTIONAL
+# define SG_NO_ARROW_OPERATOR
+
+# elif __GNUC_MINOR__ >= 8
+
+ // g++-2.8.x and egcs-1.x
+# define SG_EXPLICIT_FUNCTION_TMPL_ARGS
+# define SG_NEED_AUTO_PTR
+# define SG_MEMBER_TEMPLATES
+# define SG_NAMESPACES
+# define SG_HAVE_STD
+# define SG_HAVE_STREAMBUF
+# define SG_CLASS_PARTIAL_SPECIALIZATION
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+# define STL_STRSTREAM <strstream>
+
+# endif
+# elif __GNUC__ >= 3
+ // g++-3.0.x
+# define SG_EXPLICIT_FUNCTION_TMPL_ARGS
+# define SG_NEED_AUTO_PTR
+# define SG_MEMBER_TEMPLATES
+# define SG_NAMESPACES
+# define SG_HAVE_STD
+# define SG_HAVE_STREAMBUF
+# define SG_CLASS_PARTIAL_SPECIALIZATION
+# define SG_HAVE_STD_INCLUDES
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+# define STL_STRSTREAM <strstream>
+# else
+# error Time to upgrade. GNU compilers < 2.7 not supported
+# endif
+
+# define SG_COMPILER_STR "GNU C++ version " SG_STRINGIZE(__GNUC__) "." SG_STRINGIZE(__GNUC_MINOR__)
+
+#endif // __GNUC__
+
+/* KAI C++ */
+#if defined(__KCC)
+
+# define SG_NAMESPACES
+# define SG_HAVE_STD
+# define SG_HAVE_STREAMBUF
+# define SG_HAVE_TRAITS
+# define SG_HAVE_STD_INCLUDES
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+# define STL_STRSTREAM <strstream>
+
+# define SG_COMPILER_STR "Kai C++ version " SG_STRINGIZE(__KCC_VERSION)
+
+#endif // __KCC
+
+//
+// Metrowerks
+//
+#if defined(__MWERKS__)
+/*
+ CodeWarrior compiler from Metrowerks, Inc.
+*/
+# define SG_HAVE_TRAITS
+# define SG_HAVE_STD_INCLUDES
+# define SG_HAVE_STD
+# define SG_NAMESPACES
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+
+// Temp:
+# define bcopy(from, to, n) memcpy(to, from, n)
+
+// -rp- please use FG_MEM_COPY everywhere !
+// #define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
+
+// -dw- currently used glut has no game mode stuff
+# define GLUT_WRONG_VERSION
+
+# define SG_COMPILER_STR "Metrowerks CodeWarrior C++ version " SG_STRINGIZE(__MWERKS__)
+
+#endif // __MWERKS__
+
+//
+// Microsoft compilers.
+//
+#ifdef _MSC_VER
+# define bcopy(from, to, n) memcpy(to, from, n)
+# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
+
+# if _MSC_VER >= 1200 // msvc++ 6.0 or greater
+# define SG_NAMESPACES
+# define SG_HAVE_STD
+# define SG_HAVE_STD_INCLUDES
+# define SG_HAVE_STREAMBUF
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+# define STL_STRSTREAM <strstream>
+
+# define isnan _isnan
+# define snprintf _snprintf
+
+# pragma warning(disable: 4786) // identifier was truncated to '255' characters
+# pragma warning(disable: 4244) // conversion from double to float
+# pragma warning(disable: 4305) //
+
+# else
+# error What version of MSVC++ is this?
+# endif
+
+# define SG_COMPILER_STR "Microsoft Visual C++ version " SG_STRINGIZE(_MSC_VER)
+
+#endif // _MSC_VER
+
+#ifdef __BORLANDC__
+# if defined(HAVE_SGI_STL_PORT)
+
+// Use quotes around long file names to get around Borland's include hackery
+
+# define STL_ALGORITHM "algorithm"
+# define STL_FUNCTIONAL "functional"
+
+# define SG_MATH_EXCEPTION_CLASH
+
+# else
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRSTREAM <strstream>
+
+# define SG_INCOMPLETE_FUNCTIONAL
+
+# endif // HAVE_SGI_STL_PORT
+
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STRING <string>
+# define SG_NO_DEFAULT_TEMPLATE_ARGS
+# define SG_NAMESPACES
+// # define SG_HAVE_STD
+
+# define SG_COMPILER_STR "Borland C++ version " SG_STRINGIZE(__BORLANDC__)
+
+#endif // __BORLANDC__
+
+//
+// Native SGI compilers
+//
+
+#if defined ( sgi ) && !defined( __GNUC__ )
+# define SG_HAVE_NATIVE_SGI_COMPILERS
+
+# define SG_EXPLICIT_FUNCTION_TMPL_ARGS
+# define SG_CLASS_PARTIAL_SPECIALIZATION
+# define SG_NEED_AUTO_PTR
+# define SG_MEMBER_TEMPLATES
+# define SG_NAMESPACES
+# define SG_HAVE_STD
+# define SG_HAVE_STREAMBUF
+# define SG_HAVE_TRAITS
+# define SG_HAVE_STD_INCLUDES
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+#if (_COMPILER_VERSION < 740)
+# define STL_STRING <irix_string>
+#else
+# define STL_STRING <string>
+#endif
+# define STL_STRSTREAM <strstream>
+
+#pragma set woff 1001,1012,1014,1116,1155,1172,1174
+#pragma set woff 1401,1460,1551,1552,1681
+
+#ifdef __cplusplus
+#pragma set woff 1682,3303
+#if (_COMPILER_VERSION >= 740)
+# pragma set woff 3624
+#endif
+#endif
+
+# define SG_COMPILER_STR "SGI MipsPro compiler version " SG_STRINGIZE(_COMPILER_VERSION)
+
+#endif // Native SGI compilers
+
+
+#if defined (__sun)
+# include <strings.h>
+# include <memory.h>
+# if defined ( __cplusplus )
+ // typedef unsigned int size_t;
+ extern "C" {
+ extern void *memmove(void *, const void *, size_t);
+ }
+# else
+ extern void *memmove(void *, const void *, size_t);
+# endif // __cplusplus
+
+# if !defined( __GNUC__ )
+# define SG_COMPILER_STR "Sun compiler version " SG_STRINGIZE(__SUNPRO_CC)
+# endif
+
+#endif // sun
+
+//
+// Intel C++ Compiler
+//
+#if defined(__ICC) || defined (__ECC)
+# define SG_NAMESPACES
+# define SG_HAVE_STD
+# define SG_HAVE_STREAMBUF
+# define SG_HAVE_TRAITS
+# define SG_HAVE_STD_INCLUDES
+
+# define STL_ALGORITHM <algorithm>
+# define STL_FUNCTIONAL <functional>
+# define STL_IOMANIP <iomanip>
+# define STL_IOSTREAM <iostream>
+# define STL_ITERATOR <iterator>
+# define STL_FSTREAM <fstream>
+# define STL_STDEXCEPT <stdexcept>
+# define STL_STRING <string>
+# define STL_STRSTREAM <strstream>
+
+# define SG_COMPILER_STR "Intel C++ version " SG_STRINGIZE(__ICC)
+
+#endif // __ICC
+
+//
+// Platform dependent gl.h and glut.h definitions
+//
+
+#ifdef __APPLE__
+# define SG_GL_H <OpenGL/gl.h>
+# define SG_GLX_H <AGL/agl.h>
+# define SG_GLU_H <OpenGL/glu.h>
+# define SG_GLEXT_H <OpenGL/glext.h>
+# define SG_GLUT_H <GLUT/glut.h>
+
+inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
+#else
+# define SG_GL_H <GL/gl.h>
+# define SG_GLX_H <GL/glx.h>
+# define SG_GLU_H <GL/glu.h>
+# define SG_GLEXT_H <GL/glext.h>
+# define SG_GLUT_H <GL/glut.h>
+#endif
+
+
+//
+// No user modifiable definitions beyond here.
+//
+
+#ifdef SG_NEED_EXPLICIT
+# define explicit
+#endif
+
+#ifdef SG_NEED_TYPENAME
+# define typename
+#endif
+
+#ifdef SG_NEED_MUTABLE
+# define mutable
+#endif
+
+#ifdef SG_NEED_BOOL
+ typedef int bool;
+# define true 1
+# define false 0
+#endif
+
+#ifdef SG_EXPLICIT_FUNCTION_TMPL_ARGS
+# define SG_NULL_TMPL_ARGS <>
+#else
+# define SG_NULL_TMPL_ARGS
+#endif
+
+#ifdef SG_CLASS_PARTIAL_SPECIALIZATION
+# define SG_TEMPLATE_NULL template<>
+#else
+# define SG_TEMPLATE_NULL
+#endif
+
+// SG_NO_NAMESPACES is a hook so that users can disable namespaces
+// without having to edit library headers.
+#if defined(SG_NAMESPACES) && !defined(SG_NO_NAMESPACES)
+# define SG_NAMESPACE(X) namespace X {
+# define SG_NAMESPACE_END }
+# define SG_USING_NAMESPACE(X) using namespace X
+# else
+# define SG_NAMESPACE(X)
+# define SG_NAMESPACE_END
+# define SG_USING_NAMESPACE(X)
+#endif
+
+/** \def SG_USING_STD(x)
+ * Expands to using std::x if SG_HAVE_STD is defined
+ */
+# ifdef SG_HAVE_STD
+# define SG_USING_STD(X) using std::X
+# define STD std
+# else
+# define SG_USING_STD(X)
+# define STD
+# endif
+
+// Additional <functional> implementation from SGI STL 3.11
+// Adapter function objects: pointers to member functions
+#ifdef SG_INCOMPLETE_FUNCTIONAL
+
+template <class _Ret, class _Tp>
+class const_mem_fun_ref_t
+#ifndef __BORLANDC__
+ : public unary_function<_Tp,_Ret>
+#endif // __BORLANDC__
+{
+public:
+ explicit const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {}
+ _Ret operator()(const _Tp& __r) const { return (__r.*_M_f)(); }
+private:
+ _Ret (_Tp::*_M_f)() const;
+};
+
+template <class _Ret, class _Tp>
+inline const_mem_fun_ref_t<_Ret,_Tp> mem_fun_ref(_Ret (_Tp::*__f)() const)
+ { return const_mem_fun_ref_t<_Ret,_Tp>(__f); }
+
+#endif // SG_INCOMPLETE_FUNCTIONAL
+
+#endif // _SG_COMPILER_H
+
diff --git a/ossimPlanet/include/ossimPlanet/ioapi.h b/ossimPlanet/include/ossimPlanet/ioapi.h
new file mode 100644
index 0000000..7d457ba
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ioapi.h
@@ -0,0 +1,75 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#ifndef _ZLIBIOAPI_H
+#define _ZLIBIOAPI_H
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+
+#ifndef ZCALLBACK
+
+#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+#define ZCALLBACK CALLBACK
+#else
+#define ZCALLBACK
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+
+
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/iochannel.h b/ossimPlanet/include/ossimPlanet/iochannel.h
new file mode 100644
index 0000000..789d450
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/iochannel.h
@@ -0,0 +1,180 @@
+/**
+ * \file iochannel.hxx
+ * High level IO channel base class.
+ */
+
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: iochannel.h 10940 2007-05-16 16:04:36Z gpotts $
+
+
+#ifndef _IOCHANNEL_HXX
+#define _IOCHANNEL_HXX
+
+#include <osg/Referenced>
+#include <ossimPlanet/compiler.h>
+
+// #include "protocol.hxx"
+
+#include STL_STRING
+#include <vector>
+
+SG_USING_STD(vector);
+SG_USING_STD(string);
+
+#define SG_IO_MAX_MSG_SIZE 16384
+
+/**
+ * Specify if this is a read (IN), write (OUT), or r/w (BI) directional
+ * channel
+ */
+enum SGProtocolDir {
+ SG_IO_NONE = 0,
+ SG_IO_IN = 1,
+ SG_IO_OUT = 2,
+ SG_IO_BI = 3
+};
+
+/**
+ * Specify the channel type
+ */
+enum SGChannelType {
+ sgFileType = 0,
+ sgSerialType = 1,
+ sgSocketType = 2
+};
+
+
+/**
+ * The SGIOChannel base class provides a consistent method for
+ * applications to communication through various mediums. By providing
+ * a base class with multiple derived classes, and application such as
+ * FlightGear can implement a way to speak any protocol via any kind
+ * of I/O channel.
+ *
+ * All of the SGIOChannel derived classes have exactly the same usage
+ * interface once an instance has been created.
+ *
+ */
+class SGIOChannel :public osg::Referenced
+{
+public:
+
+ /** Constructor */
+ SGIOChannel();
+
+ /** Destructor */
+ virtual ~SGIOChannel();
+
+ /** Open a channel.
+ * @param d channel communication "direction"
+ * Direction can be one of:
+ * - SG_IO_IN - data will be flowing into this object to the application.
+ * - SG_IO_OUT - data will be flowing out of this object from the
+ * application.
+ * - SG_IO_BI - data will be flowing in both directions.
+ * - SG_IO_NONE - data will not be flowing in either direction.
+ * This is here for the sake of completeness.
+ * @return result of open
+ */
+ virtual bool open( const SGProtocolDir d );
+
+ /**
+ * The read() method is modeled after the read() Unix system
+ * call. You must provide a pointer to a character buffer that has
+ * enough allocated space for your potential read. You can also
+ * specify the maximum number of bytes allowed for this particular
+ * read. The actual number of bytes read is returned. You are
+ * responsible to ensure that the size of buf is large enough to
+ * accomodate your input message
+ * @param buf a char pointer to your input buffer
+ * @param length max number of bytes to read
+ * @return number of bytes read
+ */
+ virtual int read( char *buf, int length );
+
+ /**
+ * The readline() method is similar to read() except that it will
+ * stop at the first end of line encountered in the input buffer.
+ * @param buf a char pointer to your input buffer
+ * @param length max number of bytes to read
+ * @return number of bytes read
+ */
+ virtual int readline( char *buf, int length );
+ void setReadlineDelimiter(char delimiter='\n');
+
+
+ /**
+ * The write() method is modeled after the write() Unix system
+ * call and is analogous to the read() method. You provide a
+ * pointer to a buffer of data, and then length of that data to be
+ * written out. The number of bytes written is returned.
+ * @param buf a char pointer to your output buffer
+ * @param length number of bytes to write
+ * @return number of bytes written
+ */
+ virtual int write( const char *buf, const int length );
+
+ /**
+ * The writestring() method is a simple wrapper that will
+ * calculate the length of a null terminated character array and
+ * write it to the output channel.
+ * @param buf a char pointer to your output buffer
+ * @return number of bytes written
+ */
+ virtual int writestring( const char *str );
+
+ /**
+ * The close() method is modeled after the close() Unix system
+ * call and will close an open device. You should call this method
+ * when you are done using your IO class, before it is destructed.
+ * @return result of close
+ */
+ virtual bool close();
+
+ /**
+ * The eof() method returns true if end of file has been reached
+ * in a context where that makes sense. Otherwise it returns
+ * false.
+ * @return result of eof check
+ */
+ virtual bool eof();
+
+ inline void set_type( SGChannelType t ) { type = t; }
+ inline SGChannelType get_type() const { return type; }
+
+ inline void set_dir( const SGProtocolDir d ) { dir = d; }
+ inline SGProtocolDir get_dir() const { return dir; }
+ inline bool isvalid() const { return valid; }
+ inline void set_valid( const bool v ) { valid = v; }
+
+protected:
+ char theReadlineDelimiter;
+
+private:
+ SGChannelType type;
+ SGProtocolDir dir;
+ bool valid;
+
+};
+
+
+#endif // _IOCHANNEL_HXX
+
+
diff --git a/ossimPlanet/include/ossimPlanet/iowin32.h b/ossimPlanet/include/ossimPlanet/iowin32.h
new file mode 100644
index 0000000..a3a437a
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/iowin32.h
@@ -0,0 +1,21 @@
+/* iowin32.h -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+ This IO API version uses the Win32 API (for Microsoft Windows)
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <windows.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/mkUtils.h b/ossimPlanet/include/ossimPlanet/mkUtils.h
new file mode 100644
index 0000000..673323f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/mkUtils.h
@@ -0,0 +1,332 @@
+#ifndef MKUTILS_H
+#define MKUTILS_H
+
+// Defines namespace mkUtils containing various helpful utility functions.
+#ifdef WIN32
+#ifndef __MINGW32__
+#ifdef __MSC_VER
+# if __MSC_VER < 1600
+# include <xmath.h>
+# endif
+#endif
+#define M_LOG2E 1.44269504088896340736
+#endif
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <cmath>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <osg/Vec3>
+#include <osg/Vec4>
+#include <osg/Vec3d>
+#include <osg/Vec4d>
+#include <osg/Matrixd>
+#include <osg/Matrix>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimXmlNode.h>
+//#include <ossim/base/ossimCommon.h>
+#include <limits>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <iostream>
+
+
+namespace mkUtils
+{
+#define OSG_INNER_PRODUCT_3X3(a,b,r,c) \
+(((a(r,0)) * (b(0,c))) \
++((a(r,1)) * (b(1,c))) \
++((a(r,2)) * (b(2,c))))
+
+ OSSIMPLANET_DLL std::istream& planetSkipws(std::istream& in);
+
+ OSSIMPLANET_DLL bool writeOsgObjectToStream(std::ostream& out, const osg::Object* node, const std::string& extension);
+
+ inline void mult3x3(osg::Matrixd& result,
+ const osg::Matrixd& lhs,
+ const osg::Matrixd& rhs)
+ {
+ result(0,0) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 0, 0);
+ result(0,1) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 0, 1);
+ result(0,2) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 0, 2);
+ result(1,0) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 1, 0);
+ result(1,1) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 1, 1);
+ result(1,2) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 1, 2);
+ result(2,0) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 2, 0);
+ result(2,1) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 2, 1);
+ result(2,2) = OSG_INNER_PRODUCT_3X3(lhs, rhs, 2, 2);
+ }
+
+ inline bool almostEqual(const osg::Matrixd& lhs,
+ const osg::Matrixd& rhs,
+ double epsilon=DBL_EPSILON)
+ {
+ return ((std::fabs(lhs(0,0)-rhs(0,0)) <= epsilon) &&
+ (std::fabs(lhs(1,0)-rhs(1,0)) <= epsilon) &&
+ (std::fabs(lhs(2,0)-rhs(2,0)) <= epsilon) &&
+ (std::fabs(lhs(3,0)-rhs(3,0)) <= epsilon) &&
+ (std::fabs(lhs(0,1)-rhs(0,1)) <= epsilon) &&
+ (std::fabs(lhs(1,1)-rhs(1,1)) <= epsilon) &&
+ (std::fabs(lhs(2,1)-rhs(2,1)) <= epsilon) &&
+ (std::fabs(lhs(3,1)-rhs(3,1)) <= epsilon) &&
+ (std::fabs(lhs(0,2)-rhs(0,2)) <= epsilon) &&
+ (std::fabs(lhs(1,2)-rhs(1,2)) <= epsilon) &&
+ (std::fabs(lhs(2,2)-rhs(2,2)) <= epsilon) &&
+ (std::fabs(lhs(3,2)-rhs(3,2)) <= epsilon) &&
+ (std::fabs(lhs(0,3)-rhs(0,3)) <= epsilon) &&
+ (std::fabs(lhs(1,3)-rhs(1,3)) <= epsilon) &&
+ (std::fabs(lhs(2,3)-rhs(2,3)) <= epsilon) &&
+ (std::fabs(lhs(3,3)-rhs(3,3)) <= epsilon));
+ }
+
+ /**
+ * Gives you a nice coefficient that can be used to fade values in and out as a multiplier.
+ * Could also be used as an alpha on billboard colors and other color bindings.
+ */
+ inline double fadeCoefficient(double currentValue,
+ double referenceValue)
+ {
+ return exp( - currentValue / referenceValue );
+ }
+
+ /* template<typename T> */
+ /* inline bool almostEqual(T x, T y, T tolerence = std::numeric_limits<T>::epsilon()) */
+ /* // are x and y within tolerence distance of each other */
+ /* { return std::abs(x - y) <= tolerence; } */
+
+ inline bool hasPrefix(const std::string& s, const std::string& prefix)
+ // does s have the given prefix?
+ { return prefix == s.substr(0, prefix.size()); }
+
+ OSSIMPLANET_DLL bool hasSuffix(const std::string& s, const std::string& suffix);
+ // does s have the given suffix?
+
+ OSSIMPLANET_DLL bool isDouble(const std::string& s);
+ // does s represent a C-style double constant?
+
+ OSSIMPLANET_DLL bool isInt(const std::string& s);
+ // does s represent a C-style integer constant?
+
+ OSSIMPLANET_DLL double asDouble(const std::string& s);
+ // value of s as a double, or NAN if not a double.
+
+ inline float asFloat(const std::string& s)
+ // value of s as a float, or NAN if not a float.
+ { return static_cast<float>(asDouble(s)); }
+
+ inline long asInt(const std::string& s)
+ // value of s as a long, or 0 if not a long
+ { return strtoul(s.c_str(), NULL, 0); }
+
+ template <typename T>
+ inline std::string asString(const T& x)
+ // string representation of x
+ {
+ std::ostringstream s;
+ s.precision(16);
+ s << x;
+ return s.str();
+ }
+
+ template <typename T>
+ inline bool inInterval(T x, T a, T b)
+ // is x in the closed interval [a,b]?
+ { return x >= a && x <= b; }
+
+ template <typename T>
+ inline bool inOpenInterval(T x, T a, T b)
+ // is x in the open interval (a,b)?
+ { return x > a && x < b; }
+
+ template <typename S, typename T>
+ inline T lerp(S x, T begin, T end)
+ // linear interpolation from begin to end by x
+ { return x*(end - begin) + begin; }
+
+ template <typename T>
+ inline T inverseLerp(T x, T begin, T end)
+ // inverse of lerp
+ { return begin != end ? (x - begin)/(end - begin) : T(0); }
+
+ template <typename S, typename T>
+ T quaderp(S x, T begin, T middle, T end)
+ // quadratic interpolation through begin,middle,end by x
+ {
+ // newton interpolation
+ const T a1 = S(2)*(middle - begin);
+ const T a2 = S(2)*(end - middle) - a1;
+ return x*((x - S(0.5))*a2 + a1) + begin;
+ }
+
+ template <typename T>
+ inline T step(T x, T a)
+ // x >= a
+ { return T(x >= a); }
+
+ template <typename T>
+ T smoothstep(T x, T a, T b)
+ // like step() but smoothly over [a,b] rather than sharply at a
+ {
+ assert(a <= b);
+
+ T t = clamp((x - a)/(b - a), T(0), T(1));
+ return t*t*(T(3) - T(2)*t);
+ }
+
+ template <typename T>
+ T boxpulse(T x, T a, T b)
+ // box function that is 1 in [a,b] but 0 elsewhere
+ {
+ assert(a <= b);
+
+ return inInterval(x, a, b);
+ }
+
+ template <typename T>
+ inline T clamp(T x, T a, T b)
+ // clamp x to [a, b]
+ {
+ // assert(a <= b); // XXX we removed this, but we need to fix the real problem
+
+ return std::min(std::max(x, a), b);
+ }
+
+ template <typename T>
+ T wrap(T x, T a, T b)
+ // wrap x modularly into [a,b)
+ {
+ assert(a <= b);
+
+ if (a == b)
+ return a;
+ else {
+ T z = x < a ? b : a;
+ return std::fmod(x - z, b - a) + z;
+ }
+ }
+
+ void hprToQuat(osg::Quat& quat, const osg::Vec3d& hpr);
+ void quatToHpr(osg::Vec3d& hpr, const osg::Quat& quat);
+ bool matrixToHpr(osg::Vec3d& hpr, const osg::Matrixd& rotation );
+ bool matrixToHpr(osg::Vec3d& hpr, const osg::Matrixd& lsrMatrix,
+ const osg::Matrixd& rotationalMatrix);
+
+ inline float negativeOneNthPow(int n)
+ // compute pow(-1, n)
+ {
+ // this implementation avoids a conditional branch
+ const float possibleResults[] = {1.0, -1.0};
+ return possibleResults[n & 0x1];
+ }
+
+ template <typename T>
+ std::pair<T, T> quadraticRoots(T a, T b, T c)
+ // evaluates quadradic formula (positive sqrt is first)
+ {
+ T s = sqrt(b*b - T(4)*a*c);
+ T twoA = T(2)*a;
+ return std::pair<T, T>((-b + s)/twoA, (-b - s)/twoA);
+ }
+
+ template <typename T>
+ inline T fmodPos(T a, T b)
+ {
+ T x = std::fmod(a, b);
+ return (x < T(0)) ? x + b : x;
+ }
+
+ template <typename T>
+ inline T fmodPosAvg(T a, T b)
+ { return fmodPos(a + b*T(0.5), b) - b*T(0.5); }
+
+ template <typename T>
+ inline T fmodPosClosest(T a, T b, T c)
+ { return c + fmodPosAvg(a - c, b); }
+
+ template <typename T>
+ inline T grayCode(T x)
+ // x's binary reflected Gray code
+ { return (x >> 1) ^ x; }
+
+ template <typename T>
+ inline bool isPower2(T x)
+ // is x a power of 2? T should be integral
+ { return !(x & (x - 1)) && x; }
+
+ inline double round(double x)
+ { return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5); }
+
+ template <typename T>
+ inline T logbase(T x, T base)
+ { return log(x)/log(base); }
+
+ inline double log2(double x)
+ { return M_LOG2E*log(x); }
+
+ inline int log2int(double x)
+ { return (int)round(log2(x)); }
+
+ template <typename T>
+ T ceilPow2(T x)
+ // return the smallest power of two that is >= x; T should be integral
+ {
+ T result(1);
+ while (result < x) {
+ assert(result != 0); // assert we don't overflow result
+ result <<= 1;
+ }
+ return result;
+ }
+
+ inline osg::Vec3d modsphere2xyz(double radius, double theta, double phi)
+ // convert "modified" spherical coordinates (in radians) to cartesian coords.
+ // "modified" since angle measurements don't match mathematicians' standard conventions,
+ // instead use phi = lat and theta = lon convention, but in radians
+ { return osg::Vec3d(radius*cos(phi)*cos(theta), radius*cos(phi)*sin(theta), radius*sin(phi)); }
+
+ inline std::ostream& operator<<(std::ostream& s, const osg::Vec3f& v)
+ { return (s << v.x() << ' ' << v.y() << ' ' << v.z()); }
+ inline std::ostream& operator<<(std::ostream& s, const osg::Vec4f& v)
+ { return (s << v.x() << ' ' << v.y() << ' ' << v.z() << ' ' << v.w()); }
+ inline std::ostream& operator<<(std::ostream& s, const osg::Vec3d& v)
+ { return (s << v.x() << ' ' << v.y() << ' ' << v.z()); }
+ inline std::ostream& operator<<(std::ostream& s, const osg::Vec4d& v)
+ { return (s << v.x() << ' ' << v.y() << ' ' << v.z() << ' ' << v.w()); }
+ // convenient streaming operators not defined by osg
+
+ ossim_int64 factorial(int n);
+ // compute n!
+ // require(n >= 0 && n < 21)
+
+ void lexBraceQuotedTokens(const std::string& str, unsigned int startIdx, const char* whitespace, std::vector<std::string>* tokens, bool* unbalancedBraces);
+ // lex str into tokens starting at position start using whitespace
+ // chars as delimiters and curly braces to quote tokens containing
+ // whitespace. unbalancedBraces is true iff it aborted when detecting
+ // unbalanced braces.
+ // assert(whitespace != NULL);
+ // assert(tokens != NULL);
+ // assert(unbalancedBraces != NULL);
+
+ OSSIMPLANET_DLL bool extractObjectAndArg(std::string& resultObject,
+ std::string& resultArg,
+ const std::string& inputValue,
+ const char quotes[2] ="{}");
+ template <typename T>
+ inline void memClear(T& var)
+ // zero out a variable's memory
+ { memset(&var, 0, sizeof(T)); }
+
+ OSSIMPLANET_DLL ossimRefPtr<ossimXmlNode> newNodeFromObjectMessageRoute(const ossimString& v,
+ const char quotes[2]="{}");
+
+ OSSIMPLANET_DLL ossimRefPtr<ossimXmlNode> newNodeFromObjectMessageRoute(const ossimString& receiverPath,
+ const ossimString& command,
+ const ossimString& v,
+ const char quotes[2]);
+}
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/net.h b/ossimPlanet/include/ossimPlanet/net.h
new file mode 100644
index 0000000..e7b0c90
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/net.h
@@ -0,0 +1,12 @@
+#ifndef __PLIB_NET_H__
+#define __PLIB_NET_H__ 1
+
+#include <plib/netBuffer.h>
+#include <plib/netChannel.h>
+#include <plib/netChat.h>
+#include <plib/netMessage.h>
+#include <plib/netMonitor.h>
+#include <plib/netSocket.h>
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/netBuffer.h b/ossimPlanet/include/ossimPlanet/netBuffer.h
new file mode 100644
index 0000000..c5ff59b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/netBuffer.h
@@ -0,0 +1,234 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netBuffer.h 1901 2004-03-21 18:19:11Z sjbaker $
+*/
+
+/****
+* NAME
+* netBuffer - network buffer class
+*
+* DESCRIPTION
+* Clients and servers built on top of netBufferChannel
+* automatically support pipelining.
+*
+* Pipelining refers to a protocol capability. Normally,
+* a conversation with a server has a back-and-forth
+* quality to it. The client sends a command, and
+* waits for the response. If a client needs to send
+* many commands over a high-latency connection,
+* waiting for each response can take a long time.
+*
+* For example, when sending a mail message to many recipients
+* with SMTP, the client will send a series of RCPT commands, one
+* for each recipient. For each of these commands, the server will
+* send back a reply indicating whether the mailbox specified is
+* valid. If you want to send a message to several hundred recipients,
+* this can be rather tedious if the round-trip time for each command
+* is long. You'd like to be able to send a bunch of RCPT commands
+* in one batch, and then count off the responses to them as they come.
+*
+* I have a favorite visual when explaining the advantages of
+* pipelining. Imagine each request to the server is a boxcar on a train.
+* The client is in Los Angeles, and the server is in New York.
+* Pipelining lets you hook all your cars in one long chain; send
+* them to New York, where they are filled and sent back to you.
+* Without pipelining you have to send one car at a time.
+*
+* Not all protocols allow pipelining. Not all servers support it;
+* Sendmail, for example, does not support pipelining because it tends
+* to fork unpredictably, leaving buffered data in a questionable state.
+* A recent extension to the SMTP protocol allows a server to specify
+* whether it supports pipelining. HTTP/1.1 explicitly requires that
+* a server support pipelining.
+*
+* NOTES
+* When a user passes in a buffer object, it belongs to
+* the user. When the library gives a buffer to the user,
+* the user should copy it.
+*
+* AUTHORS
+* Sam Rushing <rushing at nightmare.com> - original version for Medusa
+* Dave McClurg <dpm at efn.org> - modified for use in PLIB
+*
+* CREATION DATE
+* Dec-2000
+*
+****/
+
+#ifndef NET_BUFFER_H
+#define NET_BUFFER_H
+
+#include "netChannel.h"
+
+
+// ===========================================================================
+// netName
+// ===========================================================================
+
+enum { NET_MAX_NAME = 31 } ;
+//eg. char name [ NET_MAX_NAME+1 ] ;
+
+
+inline char* netCopyName ( char* dst, const char* src )
+{
+ if ( src != NULL )
+ {
+ strncpy ( dst, src, NET_MAX_NAME ) ;
+ dst [ NET_MAX_NAME ] = 0 ;
+ }
+ else
+ *dst = 0 ;
+ return dst ;
+}
+
+
+// ===========================================================================
+// netBuffer
+// ===========================================================================
+
+class netBuffer
+{
+protected:
+ int length ;
+ int max_length ;
+ char* data ;
+
+public:
+ netBuffer ( int _max_length )
+ {
+ length = 0 ;
+ max_length = _max_length ;
+ data = new char [ max_length+1 ] ; //for null terminator
+ }
+
+ ~netBuffer ()
+ {
+ delete[] data ;
+ }
+
+ int getLength() const { return length ; }
+ int getMaxLength() const { return max_length ; }
+
+ /*
+ ** getData() returns a pointer to the data
+ ** Note: a zero (0) byte is appended for convenience
+ ** but the data may have internal zero (0) bytes already
+ */
+ char* getData() { data [length] = 0 ; return data ; }
+ const char* getData() const { ((char*)data) [length] = 0 ; return data ; }
+
+ void remove ()
+ {
+ length = 0 ;
+ }
+
+ void remove (int pos, int n)
+ {
+ assert (pos>=0 && pos<length && (pos+n)<=length) ;
+ //if (pos>=0 && pos<length && (pos+n)<=length)
+ {
+ memmove(&data[pos],&data[pos+n],length-(pos+n)) ;
+ length -= n ;
+ }
+ }
+
+ bool append (const char* s, int n)
+ {
+ if ((length+n)<=max_length)
+ {
+ memcpy(&data[length],s,n) ;
+ length += n ;
+ return true ;
+ }
+ return false ;
+ }
+
+ bool append (int n)
+ {
+ if ((length+n)<=max_length)
+ {
+ length += n ;
+ return true ;
+ }
+ return false ;
+ }
+} ;
+
+// ===========================================================================
+// netBufferChannel
+// ===========================================================================
+
+class netBufferChannel : public netChannel
+{
+ netBuffer in_buffer;
+ netBuffer out_buffer;
+ int should_close ;
+
+ virtual bool readable (void)
+ {
+ return (netChannel::readable() &&
+ (in_buffer.getLength() < in_buffer.getMaxLength()));
+ }
+
+ virtual void handleRead (void) ;
+
+ virtual bool writable (void)
+ {
+ return (out_buffer.getLength() || should_close);
+ }
+
+ virtual void handleWrite (void) ;
+
+public:
+
+ netBufferChannel (int in_buffer_size = 4096, int out_buffer_size = 16384) :
+ in_buffer (in_buffer_size),
+ out_buffer (out_buffer_size),
+ should_close (0)
+ { /* empty */
+ }
+
+ virtual void handleClose ( void )
+ {
+ in_buffer.remove () ;
+ out_buffer.remove () ;
+ should_close = 0 ;
+ netChannel::handleClose () ;
+ }
+
+ void closeWhenDone (void) { should_close = 1 ; }
+
+ virtual bool bufferSend (const char* msg, int msg_len)
+ {
+ if ( out_buffer.append(msg,msg_len) )
+ return true ;
+ ulSetError ( UL_WARNING, "netBufferChannel: output buffer overflow!" ) ;
+ return false ;
+ }
+
+ virtual void handleBufferRead (netBuffer& buffer)
+ {
+ /* do something here */
+ buffer.remove();
+ }
+};
+
+#endif // NET_BUFFER_H
diff --git a/ossimPlanet/include/ossimPlanet/netChannel.h b/ossimPlanet/include/ossimPlanet/netChannel.h
new file mode 100644
index 0000000..2bbc001
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/netChannel.h
@@ -0,0 +1,116 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netChannel.h 1899 2004-03-21 17:41:07Z sjbaker $
+*/
+
+/****
+* NAME
+* netChannel - network channel class
+*
+* DESCRIPTION
+* netChannel is adds event-handling to the low-level
+* netSocket class. Otherwise, it can be treated as
+* a normal non-blocking socket object.
+*
+* The direct interface between the netPoll() loop and
+* the channel object are the handleReadEvent and
+* handleWriteEvent methods. These are called
+* whenever a channel object 'fires' that event.
+*
+* The firing of these low-level events can tell us whether
+* certain higher-level events have taken place, depending on
+* the timing and state of the connection.
+*
+* AUTHORS
+* Sam Rushing <rushing at nightmare.com> - original version for Medusa
+* Dave McClurg <dpm at efn.org> - modified for use in PLIB
+*
+* CREATION DATE
+* Dec-2000
+*
+****/
+
+#ifndef NET_CHANNEL_H
+#define NET_CHANNEL_H
+
+#include "netSocket.h"
+
+class netChannel : public netSocket
+{
+ bool closed, connected, accepting, write_blocked, should_delete ;
+ netChannel* next_channel ;
+
+ friend bool netPoll (unsigned int timeout);
+
+public:
+
+ netChannel () ;
+ virtual ~netChannel () ;
+
+ void setHandle (int s, bool is_connected = true);
+ bool isConnected () const { return connected; }
+ bool isClosed () const { return closed; }
+ void shouldDelete () { should_delete = true ; }
+
+ // --------------------------------------------------
+ // socket methods
+ // --------------------------------------------------
+
+ bool open ( bool streamFlag=true ) ;
+ void close ( void ) ;
+ int listen ( int backlog ) ;
+ int connect ( const char* host, int port ) ;
+ int send ( const void * buf, int size, int flags = 0 ) ;
+ int recv ( void * buf, int size, int flags = 0 ) ;
+
+ // poll() eligibility predicates
+ virtual bool readable (void) { return (connected || accepting); }
+ virtual bool writable (void) { return (!connected || write_blocked); }
+
+ // --------------------------------------------------
+ // event handlers
+ // --------------------------------------------------
+
+ void handleReadEvent (void);
+ void handleWriteEvent (void);
+
+ // These are meant to be overridden.
+ virtual void handleClose (void) {
+ //ulSetError(UL_WARNING,"Network: %d: unhandled close",getHandle());
+ }
+ virtual void handleRead (void) {
+ //ulSetError(UL_WARNING,"Network: %d: unhandled read",getHandle());
+ }
+ virtual void handleWrite (void) {
+ //ulSetError(UL_WARNING,"Network: %d: unhandled write",getHandle());
+ }
+ virtual void handleAccept (void) {
+ //ulSetError(UL_WARNING,"Network: %d: unhandled accept",getHandle());
+ }
+ virtual void handleError (int /* error */) {
+ //ulSetError(UL_WARNING,"Network: %d: errno: %s(%d)",getHandle(),strerror(errno),errno);
+ }
+
+ static bool poll (unsigned int timeout = 0 ) ;
+ static void loop (unsigned int timeout = 0 ) ;
+};
+
+#endif // NET_CHANNEL_H
diff --git a/ossimPlanet/include/ossimPlanet/netChat.h b/ossimPlanet/include/ossimPlanet/netChat.h
new file mode 100644
index 0000000..1a89559
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/netChat.h
@@ -0,0 +1,86 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netChat.h 1568 2002-09-02 06:05:49Z sjbaker $
+*/
+
+/****
+* NAME
+* netChat - network chat class
+*
+* DESCRIPTION
+* This class adds support for 'chat' style protocols -
+* where one side sends a 'command', and the other sends
+* a response (examples would be the common internet
+* protocols - smtp, nntp, ftp, etc..).
+*
+* The handle_buffer_read() method looks at the input
+* stream for the current 'terminator' (usually '\r\n'
+* for single-line responses, '\r\n.\r\n' for multi-line
+* output), calling found_terminator() on its receipt.
+*
+* EXAMPLE
+* Say you build an nntp client using this class.
+* At the start of the connection, you'll have
+* terminator set to '\r\n', in order to process
+* the single-line greeting. Just before issuing a
+* 'LIST' command you'll set it to '\r\n.\r\n'.
+* The output of the LIST command will be accumulated
+* (using your own 'collect_incoming_data' method)
+* up to the terminator, and then control will be
+* returned to you - by calling your found_terminator()
+*
+* AUTHORS
+* Sam Rushing <rushing at nightmare.com> - original version for Medusa
+* Dave McClurg <dpm at efn.org> - modified for use in PLIB
+*
+* CREATION DATE
+* Dec-2000
+*
+****/
+
+#ifndef NET_CHAT_H
+#define NET_CHAT_H
+
+#include "netBuffer.h"
+
+class netChat : public netBufferChannel
+{
+ char* terminator;
+
+ virtual void handleBufferRead (netBuffer& buffer) ;
+
+public:
+
+ netChat () : terminator (0) {}
+
+ void setTerminator (const char* t);
+ const char* getTerminator (void);
+
+ bool push (const char* s)
+ {
+ return bufferSend ( s, strlen(s) ) ;
+ }
+
+ virtual void collectIncomingData (const char* /* s */, int /* n */) {}
+ virtual void foundTerminator (void) {}
+};
+
+#endif // NET_CHAT_H
diff --git a/ossimPlanet/include/ossimPlanet/netMessage.h b/ossimPlanet/include/ossimPlanet/netMessage.h
new file mode 100644
index 0000000..57a4a89
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/netMessage.h
@@ -0,0 +1,294 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netMessage.h 2112 2006-12-12 18:45:28Z fayjf $
+*/
+
+/****
+* NAME
+* netMessage - message buffer and channel classes
+*
+* DESCRIPTION
+* messages are a binary format for sending buffers over a channel.
+* message headers contain a type field and length.
+*
+* AUTHOR
+* Dave McClurg <dpm at efn.org>
+*
+* CREATION DATE
+* Dec-2000
+****/
+
+#ifndef __NET_MESSAGE__
+#define __NET_MESSAGE__
+
+
+#include "netBuffer.h"
+
+// ntohs() etc prototypes
+#ifdef UL_MSVC
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <arpa/inet.h>
+#endif
+
+
+class netGuid //Globally Unique IDentifier
+{
+public:
+ unsigned char data [ 16 ] ;
+
+ netGuid () {}
+
+ netGuid ( unsigned int l,
+ unsigned short w1, unsigned short w2,
+ unsigned char b1, unsigned char b2,
+ unsigned char b3, unsigned char b4,
+ unsigned char b5, unsigned char b6,
+ unsigned char b7, unsigned char b8 )
+ {
+ //store in network format (big-endian)
+
+ data[ 0] = (unsigned char)(l>>24) ;
+ data[ 1] = (unsigned char)(l>>16) ;
+ data[ 2] = (unsigned char)(l>> 8) ;
+ data[ 3] = (unsigned char)(l ) ;
+ data[ 4] = (unsigned char)(w1>>8) ;
+ data[ 5] = (unsigned char)(w1 ) ;
+ data[ 6] = (unsigned char)(w2>>8) ;
+ data[ 7] = (unsigned char)(w2 ) ;
+
+ data[ 8] = b1 ;
+ data[ 9] = b2 ;
+ data[10] = b3 ;
+ data[11] = b4 ;
+ data[12] = b5 ;
+ data[13] = b6 ;
+ data[14] = b7 ;
+ data[15] = b8 ;
+ }
+
+ bool operator ==( const netGuid& guid ) const
+ {
+ return memcmp ( data, guid.data, sizeof(data) ) == 0 ;
+ }
+
+ bool operator !=( const netGuid& guid ) const
+ {
+ return memcmp ( data, guid.data, sizeof(data) ) != 0 ;
+ }
+} ;
+
+
+class netMessage : public netBuffer
+{
+ int pos ;
+
+ void seek ( int new_pos ) const
+ {
+ if ( new_pos < 0 )
+ new_pos = 0 ;
+ else
+ if ( new_pos > length )
+ new_pos = length ;
+
+ //logical const-ness
+
+ ((netMessage*)this) -> pos = new_pos ;
+ }
+
+ void skip ( int off ) const
+ {
+ seek(pos+off);
+ }
+
+public:
+
+ // incoming message; header is already there
+ netMessage ( const char* s, int n ) : netBuffer(n)
+ {
+ assert ( n >= 5 ) ;
+ append(s,n);
+ pos = 5 ; // seek past header
+ }
+
+ // outgoing message
+ netMessage ( int type, int to_id, int from_id=0, int n=256 ) : netBuffer(n)
+ {
+ // output header
+ putw ( 0 ) ; //msg_len
+ putbyte ( type ) ;
+ putbyte ( to_id ) ;
+ putbyte ( from_id ) ;
+ }
+
+ int getType () const { return ( (unsigned char*)data )[ 2 ] ; }
+ int getToID () const { return ( (unsigned char*)data )[ 3 ] ; }
+ int getFromID () const { return ( (unsigned char*)data )[ 4 ] ; }
+ void setFromID ( int from_id ) { ( (unsigned char*)data )[ 4 ] = (unsigned char)from_id; }
+
+ void geta ( void* a, int n ) const
+ {
+ assert (pos>=0 && pos<length && (pos+n)<=length) ;
+ //if (pos>=0 && pos<length && (pos+n)<=length)
+ {
+ memcpy(a,&data[pos],n) ;
+ seek(pos+n);
+ }
+ }
+ void puta ( const void* a, int n )
+ {
+ append((const char*)a,n);
+ pos = length;
+ *((unsigned short*)data) = (unsigned short)length ; //update msg_len
+ }
+
+ int getbyte () const
+ {
+ unsigned char temp ;
+ geta(&temp,sizeof(temp)) ;
+ return temp ;
+ }
+ void putbyte ( int c )
+ {
+ unsigned char temp = c ;
+ puta(&temp,sizeof(temp)) ;
+ }
+
+ bool getb () const
+ {
+ unsigned char temp ;
+ geta(&temp,sizeof(temp)) ;
+ return temp != 0 ;
+ }
+ void putb ( bool b )
+ {
+ unsigned char temp = b? 1: 0 ;
+ puta(&temp,sizeof(temp)) ;
+ }
+
+ int getw () const
+ {
+ unsigned short temp ;
+ geta ( &temp, sizeof(temp) ) ;
+ return int ( ntohs ( temp ) ) ;
+ }
+ void putw ( int i )
+ {
+ unsigned short temp = htons ( (unsigned short) i ) ;
+ puta ( &temp, sizeof(temp) ) ;
+ }
+
+ int geti () const
+ {
+ unsigned int temp ;
+ geta ( &temp, sizeof(temp) ) ;
+ return int ( ntohl ( temp ) ) ;
+ }
+ void puti ( int i )
+ {
+ unsigned int temp = htonl ( (unsigned int) i ) ;
+ puta ( &temp, sizeof(temp) ) ;
+ }
+
+ void getfv ( float* fv, int n ) const
+ {
+ unsigned int* v = (unsigned int*)fv;
+ geta ( v, (n<<2) ) ;
+ for ( int i=0; i<n; i++ )
+ v[i] = ntohl ( v[i] ) ;
+ }
+ void putfv ( const float* fv, int n )
+ {
+ const unsigned int* v = (const unsigned int*)fv;
+ for ( int i=0; i<n; i++ )
+ {
+ unsigned int temp = htonl ( v[i] ) ;
+ puta ( &temp, sizeof(temp) ) ;
+ }
+ }
+
+ float getf () const
+ {
+ unsigned int temp ;
+ geta ( &temp, sizeof(temp) ) ;
+ temp = ntohl ( temp ) ;
+ return *((float*)&temp) ;
+ }
+ void putf ( float f )
+ {
+ unsigned int temp = *((unsigned int*)&f) ;
+ temp = htonl ( temp ) ;
+ puta ( &temp, sizeof(temp) ) ;
+ }
+
+ void gets ( char* s, int n ) const
+ {
+ char* src = &data[pos];
+ char* dst = s;
+ while (pos<length)
+ {
+ char ch = *src++;
+ if ((dst-s)<(n-1))
+ *dst++ = ch ;
+ ((netMessage*)this)->pos++;
+ if (ch==0)
+ break;
+ }
+ *dst = 0 ;
+ }
+ void puts ( const char* s )
+ {
+ puta(s,strlen(s)+1);
+ }
+
+ void print ( FILE *fd = stderr ) const
+ {
+ fprintf ( fd, "netMessage: %p, length=%d\n", this, length ) ;
+ fprintf ( fd, " header (type,to,from) = (%d,%d,%d)\n",
+ getType(), getToID(), getFromID() ) ;
+ fprintf ( fd, " data = " ) ;
+ for ( int i=0; i<length; i++ )
+ fprintf ( fd, "%02x ", data[i] ) ;
+ fprintf ( fd, "\n" ) ;
+ }
+};
+
+
+class netMessageChannel : public netBufferChannel
+{
+ virtual void handleBufferRead (netBuffer& buffer) ;
+
+public:
+
+ bool sendMessage ( const netMessage& msg )
+ {
+ return bufferSend ( msg.getData(), msg.getLength() ) ;
+ }
+
+ virtual void handleMessage ( const netMessage& msg ) {}
+};
+
+
+#endif //__NET_MESSAGE__
diff --git a/ossimPlanet/include/ossimPlanet/netMonitor.h b/ossimPlanet/include/ossimPlanet/netMonitor.h
new file mode 100644
index 0000000..d3cd6f5
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/netMonitor.h
@@ -0,0 +1,106 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netMonitor.h 1899 2004-03-21 17:41:07Z sjbaker $
+*/
+
+/****
+* NAME
+* netMonitor - network monitor server
+*
+* DESCRIPTION
+* netMonitor is a telnet command port with
+* password authorization. It can be paired
+* with and used to remotely admin another server.
+*
+* AUTHORS
+* Sam Rushing <rushing at nightmare.com> - original version for Medusa
+* Dave McClurg <dpm at efn.org> - modified for use in PLIB
+*
+* CREATION DATE
+* Dec-2000
+*
+****/
+
+#ifndef NET_MONITOR_H
+#define NET_MONITOR_H
+
+#include "netChat.h"
+
+
+class netMonitorServer : private netChannel
+{
+ char* name ;
+ char* password ;
+ char* prompt ;
+ void (*cmdfunc)(const char*) ;
+ class netMonitorChannel* active ;
+
+ friend class netMonitorChannel ;
+
+ virtual bool writable (void) { return false ; }
+ virtual void handleAccept (void) ;
+
+public:
+
+ netMonitorServer( const char* _name, int port )
+ {
+ name = ulStrDup(_name);
+ password = ulStrDup("") ;
+ prompt = ulStrDup(">>> ");
+ cmdfunc = 0 ;
+ active = 0 ;
+
+ open () ;
+ bind ("", port);
+ listen (1);
+
+ ulSetError(UL_DEBUG, "Monitor \"%s\" started on port %d",name,port);
+ }
+
+ ~netMonitorServer()
+ {
+ delete[] name ;
+ delete[] password ;
+ delete[] prompt ;
+ }
+
+ const char* getPassword () const { return password; }
+ void setPassword ( const char* string )
+ {
+ delete[] password ;
+ password = ulStrDup ( string?string:"" ) ;
+ }
+
+ void setPrompt ( const char* string )
+ {
+ delete[] prompt ;
+ prompt = ulStrDup ( string?string:"" ) ;
+ }
+
+ void setCommandFunc ( void (*func)(const char*) )
+ {
+ cmdfunc = func ;
+ }
+
+ bool push (const char* s) ;
+} ;
+
+#endif // NET_MONITOR_H
diff --git a/ossimPlanet/include/ossimPlanet/netSocket.h b/ossimPlanet/include/ossimPlanet/netSocket.h
new file mode 100644
index 0000000..c29a023
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/netSocket.h
@@ -0,0 +1,115 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netSocket.h 2052 2005-11-10 20:55:54Z fayjf $
+*/
+
+/****
+* NAME
+* netSocket - network sockets
+*
+* DESCRIPTION
+* netSocket is a thin C++ wrapper over bsd sockets to
+* facilitate porting to other platforms
+*
+* AUTHOR
+* Dave McClurg <dpm at efn.org>
+*
+* CREATION DATE
+* Dec-2000
+*
+****/
+
+#ifndef NET_SOCKET_H
+#define NET_SOCKET_H
+
+#include "ul.h"
+#include <errno.h>
+
+/*
+ * Socket address, internet style.
+ */
+class netAddress
+{
+ /* DANGER!!! This MUST match 'struct sockaddr_in' exactly! */
+ short sin_family ;
+ unsigned short sin_port ;
+ unsigned int sin_addr ;
+ char sin_zero [ 8 ] ;
+
+public:
+ netAddress () {}
+ netAddress ( const char* host, int port ) ;
+
+ void set ( const char* host, int port ) ;
+ const char* getHost () const ;
+ unsigned int getPort() const ;
+ unsigned int getIP () const ;
+ unsigned int getFamily () const ;
+ static const char* getLocalHost () ;
+
+ bool getBroadcast () const ;
+};
+
+
+/*
+ * Socket type
+ */
+class netSocket
+{
+ int handle ;
+
+public:
+
+ netSocket () ;
+ virtual ~netSocket () ;
+
+ int getHandle () const { return handle; }
+ void setHandle (int handle) ;
+
+ bool open ( bool stream=true ) ;
+ void close ( void ) ;
+ int bind ( const char* host, int port ) ;
+ int listen ( int backlog ) ;
+ int accept ( netAddress* addr ) ;
+ int connect ( const char* host, int port ) ;
+ int send ( const void * buffer, int size, int flags = 0 ) ;
+ int sendto ( const void * buffer, int size, int flags, const netAddress* to ) ;
+ int recv ( void * buffer, int size, int flags = 0 ) ;
+ int recvfrom ( void * buffer, int size, int flags, netAddress* from ) ;
+
+ void setBlocking ( bool blocking ) ;
+ void setBroadcast ( bool broadcast ) ;
+
+ static bool isNonBlockingError () ;
+ static int select ( netSocket** reads, netSocket** writes, int timeout ) ;
+} ;
+
+
+int netInit ( int* argc, char** argv = NULL ) ; /* Legacy */
+
+int netInit () ;
+
+
+const char* netFormat ( const char* fmt, ... ) ;
+
+
+#endif // NET_SOCKET_H
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanet.h b/ossimPlanet/include/ossimPlanet/ossimPlanet.h
new file mode 100644
index 0000000..2090a05
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanet.h
@@ -0,0 +1,135 @@
+#ifndef ossimPlanet_HEADER
+#define ossimPlanet_HEADER
+#include <osg/MatrixTransform>
+#include <vector>
+#include "ossimPlanetExport.h"
+#include <osg/MatrixTransform>
+#include <osgUtil/CullVisitor>
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetSousaLayer.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+
+class ossimPlanetLand;
+class OSSIMPLANET_DLL ossimPlanet : public osg::MatrixTransform,
+ public ossimPlanetActionReceiver,
+ public ossimPlanetCallbackListInterface<ossimPlanetNodeCallback>
+
+{
+public:
+ friend class ossimPlanetUpdateCallback;
+ class LayerListener : public ossimPlanetNodeCallback
+ {
+ public:
+ LayerListener(ossimPlanet* planet);
+ virtual void needsRedraw(ossimPlanetNode* node);
+ void setPlanet(ossimPlanet* planet);
+ protected:
+ ossimPlanet* thePlanet;
+ };
+ ossimPlanet();
+ virtual osg::Object* cloneType() const { return new ossimPlanet(); }
+ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ossimPlanet *>(obj)!=NULL; }
+ virtual const char* className() const { return "ossimPlanet"; }
+ virtual const char* libraryName() const { return "ossimPlanet"; }
+ virtual void setupDefaults();
+ virtual bool removeChildren(unsigned int pos,unsigned int numChildrenToRemove);
+
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual osg::BoundingSphere computeBound() const;
+ // virtual bool computeBound() const;
+ osg::ref_ptr<ossimPlanetGeoRefModel> model()
+ {
+ return theModel;
+ }
+ const osg::ref_ptr<ossimPlanetGeoRefModel> model()const
+ {
+ return theModel;
+ }
+
+ const osg::Vec3d& getEyePositionLatLonHeight()const;
+ osg::Vec3d getNadirPoint()const;
+ osg::Vec3d getLineOfSitePoint()const;
+ osg::Vec3d getNadirLatLonHeightPoint()const;
+ osg::Vec3d getLineOfSiteLatLonHeightPoint()const;
+ const osg::Vec3d& hpr()const;
+
+ void setComputeIntersectionFlag(bool flag);
+ bool getComputeIntersectionFlag()const;
+ static ossimPlanet* findPlanet(osg::Node* startNode);
+ static ossimPlanet* findPlanet(osg::NodePath& currentNodePath);
+ void resetAllRedrawFlags();
+ void setRedrawFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theRedrawFlag = flag;
+ }
+ bool redrawFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theRedrawFlag;
+ }
+ /**
+ * This executes passed in actions.
+ *
+ */
+ virtual void execute(const ossimPlanetAction& action);
+
+ void notifyNeedsRedraw(ossimPlanetNode* node);
+ const ossimPlanetLookAt* lookAt()const
+ {
+ return theLookAt.get();
+ }
+ void setLookAt(osg::ref_ptr<ossimPlanetLookAt> look)
+ {
+ theLookAt = look.get();
+ }
+ const ossimPlanetLookAt* eyePosition()const
+ {
+ return theEyePosition.get();
+ }
+ void setEyePosition(osg::ref_ptr<ossimPlanetLookAt> eye)
+ {
+ theEyePosition = eye.get();
+ }
+
+protected:
+ ~ossimPlanet();
+ virtual void xmlExecute(const ossimPlanetXmlAction& xmlAction);
+ virtual void childInserted(unsigned int pos);
+ virtual void childRemoved(unsigned int /*pos*/, unsigned int /*numChildrenToRemove*/);
+ void notifyLayerAdded(ossimPlanetLayer* layer);
+ void notifyLayerRemoved(ossimPlanetLayer* layer);
+ void computeIntersection(osgUtil::CullVisitor* cullVisitor);
+ bool theComputeIntersectionFlag;
+ bool theRedrawFlag;
+ osg::Vec3d theNadirPoint;
+ osg::Vec3d theLineOfSitePoint;
+ osg::Vec3d theNadirLatLonHeightPoint;
+ osg::Vec3d theLineOfSiteLatLonHeightPoint;
+ osg::Vec3d theEyePositionLatLonHeight;
+ mutable ossimPlanetReentrantMutex theTraversalMutex;
+ mutable ossimPlanetReentrantMutex thePropertyMutex;
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+ osg::Vec3d theLsrHeadingPitchRoll;
+ osg::ref_ptr<ossimPlanet::LayerListener> theLayerListener;
+
+ ossimPlanetReentrantMutex theLayersToAddListMutex;
+ // Internal list that is maintained through creation of layers through the
+ // recever commands. It will be synched to the graph on next Update visitation
+ //
+ std::vector<osg::ref_ptr<ossimPlanetLayer> > theLayersToAddList;
+
+ osg::ref_ptr<ossimPlanetLookAt> theLookAt;
+ osg::ref_ptr<ossimPlanetLookAt> theEyePosition;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetAction.h b/ossimPlanet/include/ossimPlanet/ossimPlanetAction.h
new file mode 100644
index 0000000..97efd35
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetAction.h
@@ -0,0 +1,161 @@
+#ifndef ossimPlanetAction_HEADER
+#define ossimPlanetAction_HEADER
+
+// message to make an ActionReceiver do something
+#include <assert.h>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Referenced>
+#include <ossim/base/ossimString.h>
+
+class ossimPlanetDestinationCommandAction;
+class ossimPlanetXmlAction;
+class OSSIMPLANET_DLL ossimPlanetAction : public osg::Referenced
+{
+public:
+ ossimPlanetAction(const ossimString& originatingFederate=ossimString());
+ ossimPlanetAction(const ossimPlanetAction& action)
+ :osg::Referenced(),
+ theOrigin(action.theOrigin),
+ theTarget(action.theTarget),
+ theCommand(action.theCommand),
+ theSourceCode(action.theSourceCode)
+ {
+
+ }
+ virtual ~ossimPlanetAction()
+ {}
+ virtual ossimPlanetDestinationCommandAction* toDestinationCommandAction()
+ {
+ return 0;
+ }
+ virtual const ossimPlanetDestinationCommandAction* toDestinationCommandAction()const
+ {
+ return 0;
+ }
+ virtual ossimPlanetXmlAction* toXmlAction()
+ {
+ return 0;
+ }
+ virtual const ossimPlanetXmlAction* toXmlAction()const
+ {
+ return 0;
+ }
+ virtual ossimPlanetAction* clone()const=0;
+ virtual ossimPlanetAction* cloneType()const=0;
+ /**
+ * Will allow one to set the source code for the derived actions
+ *
+ */
+ virtual bool setSourceCode(const ossimString& code)=0;
+ void sourceCode(ossimString& code)const
+ {
+ code = theSourceCode;
+ }
+ const ossimString& sourceCode()const
+ {
+ return theSourceCode;
+ }
+ void target(ossimString& value) const
+ {
+ value = theTarget;
+ }
+ const ossimString& target()const
+ {
+ return theTarget;
+ }
+ virtual void setTarget(const ossimString& value)
+ {
+ theTarget = value;
+ }
+
+ void command(ossimString& value) const
+ {
+ value = theCommand;
+ }
+ const ossimString& command() const
+ {
+ return theCommand;
+ }
+ virtual void setCommand(const ossimString& value)
+ {
+ theCommand = value;
+ }
+ const ossimString& origin() const
+ {
+ return theOrigin;
+ }
+
+ virtual void setOrigin(const ossimString& originatingFederate)
+ {
+ theOrigin = originatingFederate;
+ }
+
+ friend std::ostream& operator<<(std::ostream& s, const ossimPlanetAction& a)
+ {
+ a.print(s);
+ return s;
+ }
+
+ friend std::istream& operator>>(std::istream& s, ossimPlanetAction& a)
+ {
+ a.read(s);
+ return s;
+ }
+ virtual void print(std::ostream& out)const = 0;
+ virtual void read(std::istream& in) = 0;
+
+ void printError(const char* message) const;
+ void printError(const ossimString& message) const;
+ // print error message containing message followed by action source to
+ // stderr. usually called in ActionReceiver::execute() error handling.
+
+ /**
+ * post the action to the threaded action queue
+ */
+ virtual void post() const;
+
+ virtual void execute() const;
+ // execute yourself
+
+ virtual void allExecute() const;
+ // tell all machines to execute yourself (distributed sims only)
+
+ virtual void tellExecute(const ossimString& destination) const;
+ // tell another machine to execute yourself (distributed sims only)
+
+// static ossimPlanetAction createNestedAction(const ossimString& argument,
+// bool wrapWithBracketsFlag = true)
+// {
+// return createNestedAction(":dummy", "dummy", argument, wrapWithBracketsFlag);
+// }
+// static ossimPlanetAction createNestedAction(const ossimString& receiverName,
+// const ossimString& actionName,
+// const ossimString& argument,
+// bool wrapWithBracketsFlag = true)
+// {
+// if(!wrapWithBracketsFlag)
+// {
+// return ossimPlanetAction(receiverName + " " + actionName + " " + argument);
+// }
+// return ossimPlanetAction(receiverName + " " + actionName + " { " + argument + " }");
+// }
+ // streaming operators
+
+protected:
+ // federate this Action originated from (for distributed sims)
+ ossimString theOrigin;
+
+ ossimString theTarget;
+ ossimString theCommand;
+ ossimString theSourceCode;
+ static const ossimString& defaultOrigin();
+ // default origin for newly created Actions
+};
+
+
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetActionReceiver.h b/ossimPlanet/include/ossimPlanet/ossimPlanetActionReceiver.h
new file mode 100644
index 0000000..edcb5c4
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetActionReceiver.h
@@ -0,0 +1,39 @@
+#ifndef ossimPlanetActionReciever_HEADER
+#define ossimPlanetActionReciever_HEADER
+
+// abstract superclass for objects that can receive Actions.
+
+/* #include <assert> */
+#include <string>
+#include "ossimPlanetAction.h"
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetActionReceiver {
+public:
+ virtual ~ossimPlanetActionReceiver();
+
+ std::string name() const;
+ // this receiver's name, the last name in its pathname
+
+ const std::string& pathname() const
+ // this receiver's full name
+ { return pathname_; }
+
+ void setPathname(const std::string& newPath);
+
+ void setPathnameAndRegister(const std::string& newPath);
+ // call setPathname() and register *this with ActionRouter
+ // assert(newPath[0] == ':')
+
+ virtual void execute(const ossimPlanetAction& a) = 0;
+ // execute the given action
+
+protected:
+
+ std::string pathname_;
+ // this receiver's full name
+};
+
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetActionRouter.h b/ossimPlanet/include/ossimPlanet/ossimPlanetActionRouter.h
new file mode 100644
index 0000000..7536f42
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetActionRouter.h
@@ -0,0 +1,247 @@
+#ifndef ACTIONROUTER_H
+#define ACTIONROUTER_H
+
+// central router for routing Actions to all registered ActionRecievers
+
+#include <assert.h>
+#include <vector>
+#include <map>
+#include <queue>
+#include "ossimPlanetActionReceiver.h"
+#include "ossimPlanetNetworkConnection.h"
+#include "ossimPlanetExport.h"
+#include "ossimPlanetRefBlock.h"
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ScopedLock>
+#include <OpenThreads/Block>
+
+class OSSIMPLANET_DLL ossimPlanetActionRouterThreadQueue : virtual public osg::Referenced,
+ public OpenThreads::Thread
+{
+public:
+ ossimPlanetActionRouterThreadQueue()
+ :theDoneFlag(false),
+ theBlock(new ossimPlanetRefBlock)
+ {
+
+ }
+ virtual ~ossimPlanetActionRouterThreadQueue()
+ {
+ if(isRunning())
+ {
+ cancel();
+ }
+ }
+
+ virtual void run()
+ {
+ while(!theDoneFlag)
+ {
+ theBlock->block();
+ /**
+ * if we were released from the cancel then return immediately
+ */
+ if(theDoneFlag) return;
+ osg::ref_ptr<ossimPlanetAction> a;
+ theActionQueueMutex.lock();
+ if(!theActionQueue.empty())
+ {
+ a = theActionQueue.front();
+ theActionQueue.pop();
+ }
+ theActionQueueMutex.unlock();
+ if(a.valid())
+ {
+ a->execute();
+ }
+ updateThreadBlock();
+ OpenThreads::Thread::YieldCurrentThread();
+ }
+ }
+ virtual int cancel()
+ {
+ int result = 0;
+
+ if( isRunning() )
+ {
+ theDoneFlag = true;
+ theBlock->release();
+
+ while(isRunning())
+ {
+ OpenThreads::Thread::YieldCurrentThread();
+ }
+ }
+ return result;
+ }
+ void updateThreadBlock()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionQueueMutex);
+ theBlock->set(!theActionQueue.empty());
+ }
+ void setDoneFlag(bool flag)
+ {
+ theDoneFlag = flag;
+ }
+ void addAction(const ossimPlanetAction& action)
+ {
+ theActionQueueMutex.lock();
+ theActionQueue.push(action.clone());
+ theActionQueueMutex.unlock();
+ updateThreadBlock();
+ }
+protected:
+ bool theDoneFlag;
+ osg::ref_ptr<ossimPlanetRefBlock> theBlock;
+ mutable ossimPlanetReentrantMutex theActionQueueMutex;
+ std::queue<osg::ref_ptr<ossimPlanetAction> > theActionQueue;
+};
+
+class OSSIMPLANET_DLL ossimPlanetActionRouter : public ossimPlanetActionReceiver
+{
+public:
+ typedef std::map<std::string, ossimPlanetActionReceiver*> MapType;
+ // initialize/shutdown
+
+ static ossimPlanetActionRouter* instance();
+ // pointer to the lazy initialized ActionRouter singleton
+ // assert(instance() != NULL)
+
+ static void shutdown();
+ // clean up the singleton
+
+ // network
+
+ void addNetworkConnection(ossimPlanetNetworkConnection* commLink);
+ // add an external communication interface to be used
+ // require(commLink != NULL && commLink->error().empty())
+
+ void removeNetworkConnection(const ossimString& name);
+ // remove the named external communication interface from use
+ // NB: this routine will not call delete on the removed connection!
+
+ ossimPlanetNetworkConnection* networkConnection(const ossimString& name) const;
+ // return the NetworkConnection with the given name or NULL if nonexistent
+
+ // federate name
+
+ const ossimString& federateName() const
+ // the name of this federate as seen from the network
+ { return federateName_; }
+
+ void setFederateName(const ossimString& newName);
+ // set the network name of this federate
+ // require(!newName.empty())
+ // require(newName.find(' ', 0) <= 0)
+ // ensure(newName == federateName())
+
+ /**
+ * This will post to the thread queue the action to route and route it later
+ */
+ void post(const ossimPlanetAction& a);
+
+ /**
+ * Routes the Action immediately.
+ */
+ void route(const ossimPlanetAction& a);
+ // cause the action's target to execute() the Action on the local machine
+
+ void allRoute(const ossimPlanetAction& a);
+ // cause the action's target to execute() the Action on
+ // the local machine as well as all machines in the
+ // distributed sim.
+
+ void tellRoute(const ossimPlanetAction& a, const ossimString& destination);
+ // cause the action's target to execute() the Action on
+ // the the destination machine
+ // require(!destination.empty())
+
+ void executeFile(const ossimString& filename, const ossimString& origin = ossimPlanetActionRouter::instance()->federateName());
+ // sequentially call execute() on each Action in the file,
+ // with all Actions having origin as their origin.
+
+ void executeNetworkActions();
+ // call execute() on pending Actions on all NetworkConnections
+
+ // ActionReceiver management
+
+ void registerReceiver(ossimPlanetActionReceiver* r);
+ // r should receive actions
+ // assert(r != NULL)
+ // assert(receiver(r->pathName()) == r)
+
+ void unregisterReceiver(ossimPlanetActionReceiver* r);
+ // r should no longer receive actions
+ // assert(r != NULL)
+ // assert(receiver(r->pathname()) != r)
+
+ ossimPlanetActionReceiver* receiver(const ossimString& receiverPathname) const;
+ // the object with the specified pathname
+ // assert(result == NULL || result->pathName() == receiverPathname)
+
+ void printReceivers();
+ // print the list of receivers
+
+ // ActionReceiver features
+
+ void execute(const ossimPlanetAction& a);
+ // execute the given action
+
+protected:
+
+ // hide these to enforce singleton
+ ossimPlanetActionRouter();
+ ~ossimPlanetActionRouter();
+ ossimPlanetActionRouter(const ossimPlanetActionRouter &other):ossimPlanetActionReceiver(other) { assert(false);}
+ ossimPlanetActionRouter& operator=(const ossimPlanetActionRouter &) { assert(false); return *this;}
+
+ static ossimPlanetActionRouter* instance_;
+ osg::ref_ptr<ossimPlanetActionRouterThreadQueue> theThreadQueue;
+ // our singleton instance
+ mutable ossimPlanetReentrantMutex theReceiverMutex;
+ MapType receivers_;
+ std::vector<ossimPlanetNetworkConnection*> network_;
+ // receiver name/object pairs
+
+ ossimString federateName_;
+ // this federate's name
+
+ void remoteRouteImplementation(const ossimPlanetAction& a, const ossimString& destination);
+ // implementation for allRoute() and tellRoute()
+
+ // STL equality predicate used to find a NetworkConnection by name
+ class NCEqualPred
+ {
+ public:
+ NCEqualPred(const ossimString& n) : targetName_(n) {}
+ const ossimString& targetName_;
+ bool operator()(const ossimPlanetNetworkConnection* i) const
+ { return i->name() == targetName_.string(); }
+ };
+};
+
+inline ossimPlanetActionRouter* ossimPlanetActionRouter::instance()
+{
+ if (instance_ == 0)
+ {
+ instance_ = new ossimPlanetActionRouter;
+ instance_->theThreadQueue = new ossimPlanetActionRouterThreadQueue;
+ instance_->theThreadQueue->setDoneFlag(false);
+ instance_->theThreadQueue->start();
+ }
+/* assert(instance_ != NULL); */
+ return instance_;
+}
+
+inline void ossimPlanetActionRouter::shutdown()
+{
+ if(instance_)
+ {
+ delete instance_;
+ instance_ = 0;
+ }
+}
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetAnimatedPointModel.h b/ossimPlanet/include/ossimPlanet/ossimPlanetAnimatedPointModel.h
new file mode 100644
index 0000000..208bba0
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetAnimatedPointModel.h
@@ -0,0 +1,68 @@
+#ifndef ossimPlanetAnimatedPointModel_HEADER
+#define ossimPlanetAnimatedPointModel_HEADER
+#include <ossimPlanet/ossimPlanetPointModel.h>
+#include <ossimPlanet/ossimPlanetAnimationPath.h>
+#include <osg/Geode>
+#include <osg/MatrixTransform>
+#include <osg/Geometry>
+#include <osg/LineWidth>
+#include <OpenThreads/Mutex>
+
+class OSSIMPLANET_DLL ossimPlanetAnimatedPointModel : public ossimPlanetAnnotationLayerNode
+{
+public:
+ ossimPlanetAnimatedPointModel();
+ virtual ~ossimPlanetAnimatedPointModel();
+ void execute(const ossimPlanetAction& action);
+ void setAnimationPath(ossimPlanetAnimationPath* path);
+ void setAnimationPathColor(const osg::Vec4f& value);
+ void setAnimationPathLineThickness(ossim_float32 value);
+ void setShowPathFlag(bool flag);
+ void setShowModelFlag(bool flag);
+ void setPointModel(osg::Node* value);
+ void setTimeScale(ossim_float64 scale);
+ void setTimeOffset(ossim_float64 offset);
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual void stage();
+
+ osg::Node* pointModel(){return thePointModel.get();}
+ const osg::Node* pointModel()const{return thePointModel.get();}
+ ossimPlanetAnimationPath* animationPath(){return theAnimationPath.get();}
+ const ossimPlanetAnimationPath* animationPath()const{return theAnimationPath.get();}
+
+protected:
+ void updateCoordinates();
+ void updateColor();
+ class OSSIMPLANET_DLL PathCallback : public osg::AnimationPathCallback
+ {
+ public:
+ PathCallback();
+ PathCallback(const PathCallback& apc,
+ const osg::CopyOp& copyop);
+ PathCallback(osg::AnimationPath* ap,
+ double timeOffset=0.0,
+ double timeMultiplier=1.0);
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
+ };
+ OpenThreads::Mutex theUpdateCoordinatesMutex;
+ OpenThreads::Mutex theUpdateColorMutex;
+ bool theShowPathFlag;
+ bool theShowModelFlag;
+ osg::Vec4f theAnimationPathColor;
+ ossim_float32 theAnimationPathLineThickness;
+ osg::ref_ptr<osg::Node> thePointModel;
+ osg::ref_ptr<ossimPlanetAnimationPath> theAnimationPath;
+
+ // need drawing for the path
+ //
+ osg::ref_ptr<osg::MatrixTransform> thePathMatrixTransform;
+ osg::ref_ptr<osg::Vec4Array> thePathColor;
+ osg::ref_ptr<osg::Vec3Array> thePathVertices;
+ osg::ref_ptr<osg::LineWidth> theLineWidth;
+ osg::ref_ptr<osg::Geode> thePathGeode;
+ osg::ref_ptr<osg::Geometry> thePathGeometry;
+
+ osg::ref_ptr<PathCallback> theAnimationPathCallback;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetAnimationPath.h b/ossimPlanet/include/ossimPlanet/ossimPlanetAnimationPath.h
new file mode 100644
index 0000000..32edfdb
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetAnimationPath.h
@@ -0,0 +1,92 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: Garrett Potts
+//
+//*************************************************************************
+// $Id$
+#ifndef ossimPlanetAnimationPath_HEADER
+#define ossimPlanetAnimationPath_HEADER
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/AnimationPath>
+class OSSIMPLANET_DLL ossimPlanetAnimationPath : public osg::AnimationPath
+{
+public:
+ class OSSIMPLANET_DLL Tuple
+ {
+ public:
+ Tuple(const osg::Vec3d& pos,
+ const osg::Vec3d& orient,
+ const osg::Vec3d& s = osg::Vec3(1.0,1.0,1.0))
+ :thePosition(pos),
+ theOrientation(orient),
+ theScale(s)
+ {
+
+ }
+ const osg::Vec3d& position()const{return thePosition;}
+ const osg::Vec3d& orientation()const{return theOrientation;}
+ const osg::Vec3d& scale()const{return theScale;}
+ void setPosition(const osg::Vec3d& value){thePosition = value;}
+ void setScale(const osg::Vec3d& value){theScale = value;}
+ void setOrientation(const osg::Vec3d& value){theOrientation = value;}
+
+ osg::Vec3d thePosition;
+ osg::Vec3d theOrientation;
+ osg::Vec3d theScale;
+ };
+
+ typedef std::map<double, Tuple> TimeTupleMap;
+ class OSSIMPLANET_DLL GeospatialPath : public osg::Referenced
+ {
+ public:
+ GeospatialPath(){}
+ bool empty()const{return theTimeTupleMap.empty();}
+ TimeTupleMap& timeTupleMap(){return theTimeTupleMap;}
+ const TimeTupleMap& timeTupleMap()const{return theTimeTupleMap;}
+ double firstTime() const { if (!theTimeTupleMap.empty()) return theTimeTupleMap.begin()->first; else return 0.0;}
+ double lastTime() const { if (!theTimeTupleMap.empty()) return theTimeTupleMap.rbegin()->first; else return 0.0;}
+ double period() const { return lastTime()-firstTime();}
+ protected:
+ TimeTupleMap theTimeTupleMap;
+ };
+ typedef std::vector<osg::Vec3d> PointList;
+ ossimPlanetAnimationPath();
+ void setGeoRefModel(ossimPlanetGeoRefModel* model){theModel = model;}
+ ossimPlanetGeoRefModel* geoRefModel(){return theModel.get();}
+ const ossimPlanetGeoRefModel* geoRefModel()const{return theModel.get();}
+ bool openAnimationPathByXmlDocument(const ossimFilename& animationFile);
+ bool setAnimationPathByXmlDocument(const ossimString& xml);
+ bool setAnimationPathByXmlDocument(std::istream& xmlStream);
+ bool openAnimationPathByXmlNode(const ossimFilename& animationFile);
+ bool setAnimationPathByXmlNode(const ossimString& xml);
+ bool setAnimationPathByXmlNode(std::istream& xmlStream);
+
+ bool setAnimationPathByXmlNode(ossimRefPtr<ossimXmlNode> node);
+ ossimXmlNode* saveXml()const;
+ GeospatialPath* geospatialPath(){return thePath.get();};
+ const GeospatialPath* geospatialPath()const{return thePath.get();};
+ void setGeospatialPath(GeospatialPath* path);
+ virtual bool getInterpolatedControlPoint(double time,
+ osg::AnimationPath::ControlPoint& controlPoint) const;
+
+ bool generateWorldCoordinates(PointList& worldPoints)const;
+ bool generateModelCoordinates(PointList& modelPoints)const;
+
+ bool moveToLocationLatLon(const osg::Vec2d& llh);
+
+
+protected:
+ virtual double adjustTime(double time)const;
+ void lsrMatrix(osg::Matrixd& result,
+ const Tuple& tuple)const;
+ osg::ref_ptr<GeospatialPath> thePath;
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+};
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetAnnotationLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetAnnotationLayer.h
new file mode 100644
index 0000000..c1450fa
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetAnnotationLayer.h
@@ -0,0 +1,83 @@
+#ifndef ossimPlanetAnnotationLayer_HEADER
+#define ossimPlanetAnnotationLayer_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetRefBlock.h>
+#include <osg/Image>
+#include <osg/Texture2D>
+#include <osg/ref_ptr>
+#include <osgText/Font>
+#include <ossimPlanet/ossimPlanetAnnotationLayerNode.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <queue>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+
+class OSSIMPLANET_DLL ossimPlanetAnnotationLayer : public ossimPlanetLayer
+{
+public:
+ class Stager : public ossimPlanetOperation
+ {
+ public:
+ Stager(ossimPlanetAnnotationLayerNode* node)
+ :theNode(node)
+ {
+
+ }
+ virtual void run()
+ {
+ if(theNode.valid())
+ {
+ theNode->stage();
+ }
+ }
+ protected:
+ osg::ref_ptr<ossimPlanetAnnotationLayerNode> theNode;
+ };
+ ossimPlanetAnnotationLayer();
+ virtual ~ossimPlanetAnnotationLayer();
+ virtual osg::Object* cloneType() const { return new ossimPlanetAnnotationLayer(); }
+ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ossimPlanetAnnotationLayer *>(obj)!=0; }
+ virtual const char* className() const { return "ossimPlanetAnnotationLayer"; }
+ virtual const char* libraryName() const { return "ossimPlanet"; }
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual void execute(const ossimPlanetAction& a);
+ osg::ref_ptr<osg::Texture2D> defaultIconTexture()
+ {
+ return theDefaultIconTexture;
+ }
+ osg::ref_ptr<osgText::Font> defaultFont()
+ {
+ return theDefaultFont.get();
+ }
+ const osg::ref_ptr<osgText::Font> defaultFont()const
+ {
+ return theDefaultFont.get();
+ }
+ void removeByNameAndId(const ossimString& name, const ossimString& id);
+
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> stagingThreadQueue()
+ {
+ return theStagingThreadQueue;
+ }
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> updateThreadQueue()
+ {
+ return theUpdateThreadQueue;
+ }
+protected:
+ virtual void nodeAdded(osg::Node* node);
+ virtual void nodeRemoved(osg::Node* node);
+ virtual void needsRemoving(osg::Node* node);
+ osg::ref_ptr<osgText::Font> theDefaultFont;
+ osg::ref_ptr<osg::Image> theDefaultIconImage;
+ osg::ref_ptr<osg::Texture2D> theDefaultIconTexture;
+ mutable ossimPlanetReentrantMutex theGraphMutex;
+
+
+ ossimPlanetReentrantMutex theNodesToRemoveListMutex;
+ NodeListType theNodesToRemoveList;
+
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> theStagingThreadQueue;
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> theUpdateThreadQueue;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetAnnotationLayerNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetAnnotationLayerNode.h
new file mode 100644
index 0000000..b4f018a
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetAnnotationLayerNode.h
@@ -0,0 +1,453 @@
+#ifndef ossimPlanetAnnotationLayerNode_HEADER
+#define ossimPlanetAnnotationLayerNode_HEADER
+#include <ossimPlanet/ossimPlanetNode.h>
+#include <ossim/base/ossimNotify.h>
+#include <osg/ref_ptr>
+#include <osg/Geometry>
+#include <osg/Vec3d>
+#include <osg/ClusterCullingCallback>
+#include <osg/Matrixd>
+#include <osg/Geode>
+#include <osg/MatrixTransform>
+#include <osg/Timer>
+#include <ossimPlanet/ossimPlanetFadeText.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <osg/Vec4d>
+enum ossimPlanetAnnotationColorMode
+{
+ ossimPlanetAnnotationColorMode_NORMAL = 0,
+ ossimPlanetAnnotationColorMode_RANDOM = 1
+};
+
+class OSSIMPLANET_DLL ossimPlanetAnnotationExpireTime : public osg::Referenced
+{
+public:
+ ossimPlanetAnnotationExpireTime(){}
+ virtual void initTimeStamp()=0;
+ virtual bool hasExpired()const=0;
+};
+
+class OSSIMPLANET_DLL ossimPlanetAnnotationColorStyle : public osg::Referenced
+{
+public:
+ ossimPlanetAnnotationColorStyle()
+ :theColor(1.0,1.0,1.0,1.0),
+ theColorMode(ossimPlanetAnnotationColorMode_NORMAL)
+ {
+ }
+ void setColor(const osg::Vec4d& color)
+ {
+ theColor = color;
+ }
+ const osg::Vec4d& color()const
+ {
+ return theColor;
+ }
+ void color(osg::Vec4d& value)const
+ {
+ value = theColor;
+ }
+ void setColorMode(ossimPlanetAnnotationColorMode mode)
+ {
+ theColorMode = mode;
+ }
+ ossimPlanetAnnotationColorMode colorMode()const
+ {
+ return theColorMode;
+ }
+protected:
+ osg::Vec4d theColor;
+ ossimPlanetAnnotationColorMode theColorMode;
+};
+
+class OSSIMPLANET_DLL ossimPlanetAnnotationLabelStyle : public ossimPlanetAnnotationColorStyle
+{
+public:
+ ossimPlanetAnnotationLabelStyle()
+ :theScale(1.0)
+ {
+ }
+ void setScale(ossim_float64 scale)
+ {
+ theScale = scale;
+ }
+ ossim_float64 scale()const
+ {
+ return theScale;
+ }
+protected:
+ ossim_float64 theScale;
+};
+
+class OSSIMPLANET_DLL ossimPlanetAnnotationExpireDuration : public ossimPlanetAnnotationExpireTime
+{
+public:
+ ossimPlanetAnnotationExpireDuration(double duration=0.0)
+ :theDuration(duration),
+ theUnit(ossimPlanetTimeUnit_SECONDS),
+ theInitialStamp(osg::Timer::instance()->tick())
+ {
+ }
+ double duration()const
+ {
+ return theDuration;
+ }
+ void setDuration(double value)
+ {
+ theDuration = value;
+ }
+ ossimPlanetTimeUnit unit()const
+ {
+ return theUnit;
+ }
+ virtual void initTimeStamp()
+ {
+ theInitialStamp = osg::Timer::instance()->tick();
+ }
+ virtual bool hasExpired()const
+ {
+ return osg::Timer::instance()->delta_s(theInitialStamp, osg::Timer::instance()->tick())>=theDuration;
+ }
+protected:
+ double theDuration;
+ ossimPlanetTimeUnit theUnit;
+ osg::Timer_t theInitialStamp;
+};
+class ossimPlanetAnnotationGroupNode;
+class OSSIMPLANET_DLL ossimPlanetAnnotationLayerNode : public ossimPlanetNode
+{
+public:
+ enum DirtyBit
+ {
+ NOT_DIRTY = 0,
+ COORDINATE_DIRTY = 1,
+ COLOR_DIRTY = 2,
+ LABEL_DIRTY = 4,
+ ICON_DIRTY = 8,
+ MATRIX_DIRTY = 16,
+ GENERIC_DIRTY = 32,
+ ALL_DIRTY = (COORDINATE_DIRTY|COLOR_DIRTY|ICON_DIRTY|LABEL_DIRTY|MATRIX_DIRTY|GENERIC_DIRTY)
+ };
+ ossimPlanetAnnotationLayerNode();
+
+ /**
+ * Xml formatted custom data.
+ */
+ void setExtendedData(const ossimString& value);
+ virtual void execute(const ossimPlanetAction& action);
+ virtual void update(){};
+ virtual void stage()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theStagedFlag = true;
+ }
+ virtual bool isStaged()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theStagedFlag;
+ }
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ void setStagedFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theStagedFlag = flag;
+ }
+ virtual ossimPlanetAnnotationGroupNode* asAnnotationGroup()
+ {
+ return 0;
+ }
+ virtual const ossimPlanetAnnotationGroupNode* asAnnotationGroup()const
+ {
+ return 0;
+ }
+ void setDirtyBits(DirtyBit bit)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theDirtyBit = bit;
+ }
+ void setDirtyBit(DirtyBit bit)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theDirtyBit |= (ossim_uint32)bit;
+ }
+ void clearDirtyBit(DirtyBit bit)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+
+ theDirtyBit &= (~((ossim_uint32)bit));
+ }
+ bool isDirtyBitSet(DirtyBit bit)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (theDirtyBit & bit);
+ }
+protected:
+ mutable ossimPlanetReentrantMutex thePropertyMutex;
+ ossim_uint32 theDirtyBit;
+ bool theStagedFlag;
+ osg::ref_ptr<ossimPlanetAnnotationExpireTime> theExpireTime;
+};
+
+class ossimPlanetAnnotationPoint;
+class OSSIMPLANET_DLL ossimPlanetAnnotationGeometry : public osg::Referenced
+{
+public:
+ ossimPlanetAnnotationGeometry()
+ :theExtrudeFlag(false),
+ theAltitudeMode(ossimPlanetAltitudeMode_CLAMP_TO_GROUND)
+ {
+
+ }
+ virtual void setExtrudeFlag(bool flag)
+ {
+ theExtrudeFlag = flag;
+ }
+ virtual void setAltitudeMode(ossimPlanetAltitudeMode mode)
+ {
+ theAltitudeMode = mode;
+ }
+ ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+ virtual ossimPlanetAnnotationPoint* asPoint()
+ {
+ return 0;
+ }
+ virtual const ossimPlanetAnnotationPoint* asPoint()const
+ {
+ return 0;
+ }
+ virtual void traverse( osg::NodeVisitor& nv)=0;
+protected:
+ bool theExtrudeFlag;
+ ossimPlanetAltitudeMode theAltitudeMode;
+};
+
+class ossimPlanetAnnotationPoint: public ossimPlanetAnnotationGeometry
+{
+public:
+ ossimPlanetAnnotationPoint(const osg::Vec3d& coordinate=osg::Vec3d(0.0,0.0,0.0))
+ :theCoordinate(coordinate)
+ {
+
+ }
+ virtual ossimPlanetAnnotationPoint* asPoint()
+ {
+ return this;
+ }
+ virtual const ossimPlanetAnnotationPoint* asPoint()const
+ {
+ return this;
+ }
+ void setCoordinate(const osg::Vec3d& coordinate)
+ {
+ theCoordinate = coordinate;
+ }
+ const osg::Vec3d& coordinate()const
+ {
+ return theCoordinate;
+ }
+ void setModelCoordinate(const osg::Vec3d& modelCoordinate)
+ {
+ theModelCoordinate = modelCoordinate;
+ }
+ const osg::Vec3d& modelCoordinate()const
+ {
+ return theModelCoordinate;
+ }
+ virtual void traverse( osg::NodeVisitor& nv)
+ {
+ if(theMatrixTransform.valid())
+ {
+ theMatrixTransform->accept(nv);
+ }
+ }
+ void setMatrixTransform(osg::ref_ptr<osg::MatrixTransform> m)
+ {
+ theMatrixTransform = m;
+ }
+ osg::ref_ptr<osg::MatrixTransform> matrixTransform()
+ {
+ return theMatrixTransform;
+ }
+ const osg::ref_ptr<osg::MatrixTransform> matrixTransform()const
+ {
+ return theMatrixTransform;
+ }
+
+protected:
+ osg::Vec3d theCoordinate;
+ osg::Vec3d theModelCoordinate;
+ osg::Vec3d theLocalCoordinate;
+ osg::ref_ptr<osg::MatrixTransform> theMatrixTransform;
+};
+
+
+class ossimPlanetAnnotationGroupNode : public ossimPlanetAnnotationLayerNode
+{
+public:
+ ossimPlanetAnnotationGroupNode()
+ {
+
+ }
+ virtual ossimPlanetAnnotationGroupNode* asAnnotationGroup()
+ {
+ return this;
+ }
+ virtual const ossimPlanetAnnotationGroupNode* asAnnotationGroup()const
+ {
+ return this;
+ }
+ virtual bool addChild( Node *child )
+ {
+ ossimPlanetAnnotationLayerNode* annotationLayerNode = dynamic_cast<ossimPlanetAnnotationLayerNode*>(child);
+ if(annotationLayerNode)
+ {
+ return ossimPlanetAnnotationLayerNode::addChild(annotationLayerNode);
+ }
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetAnnotationGroupNode::addChild: Only annotation layer nodes allowed to be added to an Annotation group\n";
+ return false;
+ }
+ virtual void stage()
+ {
+
+ }
+ virtual void update()
+ {
+
+ }
+protected:
+
+};
+class ossimPlanetAnnotationTextGeode : public osg::Geode
+{
+public:
+ ossimPlanetAnnotationTextGeode(ossimPlanetNode* layerNode,
+ ossimPlanetFadeText* text)
+ :theLayerNode(layerNode),
+ theText(text)
+ {
+ if(text)
+ {
+ addDrawable(text);
+ }
+ setUpdateCallback(new ossimPlanetTraverseCallback);
+ setCullCallback(new ossimPlanetTraverseCallback);
+ getOrCreateStateSet()->setMode(GL_BLEND,osg::StateAttribute::ON);
+ getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
+
+ }
+ virtual void traverse(osg::NodeVisitor& nv)
+ {
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ theSavedOpacity = theText->opacity();
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ osg::Geode::traverse(nv);
+ if(theSavedOpacity!=theText->opacity())
+ {
+ if(theLayerNode)
+ {
+ theLayerNode->setRedrawFlag(true);
+ }
+ }
+ }
+
+protected:
+ ossim_float64 theSavedOpacity;
+ ossimPlanetNode* theLayerNode;
+ ossimPlanetFadeText* theText;
+};
+
+class OSSIMPLANET_DLL ossimPlanetAnnotationPlacemark : public ossimPlanetAnnotationLayerNode
+{
+public:
+ class PlacemarkUpdater;
+ friend class PlacemarkUpdater;
+ ossimPlanetAnnotationPlacemark();
+ ossimPlanetAnnotationPlacemark(const osg::Vec3d& location,
+ ossimPlanetAltitudeMode altitudeMode,
+ const ossimString& nameStr = "",
+ const ossimString& descriptionStr = "");
+ virtual void execute(const ossimPlanetAction& action);
+ virtual void stage();
+ virtual void update();
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual void setName(const ossimString& name);
+ const osg::ref_ptr<ossimPlanetFadeText> label()const
+ {
+ return theLabel.get();
+ }
+ osg::ref_ptr<ossimPlanetFadeText> label()
+ {
+ return theLabel.get();
+ }
+ const osg::ref_ptr<ossimPlanetAnnotationTextGeode> labelGeode()const
+ {
+ return theLabelGeode.get();
+ }
+ osg::ref_ptr<ossimPlanetAnnotationTextGeode> labelGeode()
+ {
+ return theLabelGeode.get();
+ }
+ const osg::ref_ptr<ossimPlanetAnnotationGeometry> geometry()const
+ {
+ return theGeometry;
+ }
+ osg::ref_ptr<osg::ClusterCullingCallback> clusterCull()
+ {
+ return theClusterCull;
+ }
+ const osg::ref_ptr<osg::ClusterCullingCallback> clusterCull()const
+ {
+ return theClusterCull;
+ }
+
+ const osg::ref_ptr<ossimPlanetAnnotationLabelStyle> labelStyle()const
+ {
+ return theLabelStyle;
+ }
+ osg::ref_ptr<ossimPlanetAnnotationGeometry> geometry()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGeometryMutex);
+ return theGeometry;
+ }
+ void setGeometry(osg::ref_ptr<ossimPlanetAnnotationGeometry> geom)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGeometryMutex);
+ theGeometry = geom;
+ }
+ virtual void setEnableFlag(bool flag)
+ {
+ if(enableFlag()!=flag)
+ {
+ if(theLabel.valid())
+ {
+ theLabel->setOpacity(0.0);
+ }
+ }
+ ossimPlanetAnnotationLayerNode::setEnableFlag(flag);
+ }
+protected:
+ mutable ossimPlanetReentrantMutex theUpdateMutex;
+ osg::ref_ptr<osg::ClusterCullingCallback> theClusterCull;
+ osg::ref_ptr<ossimPlanetAnnotationTextGeode> theLabelGeode;
+ mutable ossimPlanetReentrantMutex theGeometryMutex;
+ osg::ref_ptr<ossimPlanetAnnotationGeometry> theGeometry;
+ osg::ref_ptr<ossimPlanetFadeText> theLabel;
+
+ osg::ref_ptr<ossimPlanetAnnotationLabelStyle> theLabelStyle;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetApi.h b/ossimPlanet/include/ossimPlanet/ossimPlanetApi.h
new file mode 100644
index 0000000..d4619d6
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetApi.h
@@ -0,0 +1,770 @@
+#ifndef ossimPlanetViewApi_HEADER
+#define ossimPlanetViewApi_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimConstants.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+ /**
+ * ossimPlanet_StatePtr is the main pointer. All API calls will manpulate this state pointer.
+ * It will hold the planet layers, views, manipulators, ... etc. ossimPlanet_PlanetPtr is the native pointer
+ * to a Planet Object. The ossimPlanet_LayerPtr is the native pointer to a Planet layer. *
+ */
+ typedef void* ossimPlanet_StatePtr;
+ typedef void* ossimPlanet_PlanetPtr;
+ typedef void* ossimPlanet_LayerPtr;
+ typedef ossim_int64 ossimPlanet_IndexType;
+ typedef ossim_uint64 ossimPlanet_SizeType;
+ typedef const char* ossimPlanet_ConstStringType;
+ typedef char* ossimPlanet_StringType;
+
+ /**
+ * The context type determines how much you want the API to manage and handle. There
+ * are 3 ways you probably would like to use the library.
+ *
+ * - ossimPlanet_VIEWER_CONTEXT option is typical of a full command line application that all
+ * you are concerned about is scripting and running a full screen or windowed planet. This
+ * will interface into osg::Viewer.
+ * - ossimPlanet_NOVIEWER_CONTEXT option is used to embed the scenegraph and bridge view parameters.
+ * There are 2 situations when you want to do this and both require that you create your own GL context and manage it.
+ * The first situation is if Planet is the drawable and you are in a GUI environment that creates a Gl context for you.
+ * you just make it current and then draw the planet and use the API to bridge view parameters and manipulate layers.
+ * The second situation is if you have a full GL application that you wrote and all you want to do is embed the planet
+ * as a drawable then use this context.
+ * - ossimPlanet_PLANET_ONLY_CONTEXT option is used when you are wanting to use the API only to interface into the manipulation of the planet layers.
+ * Typically this is done if you have your own OpenSceneGraph and your own View and gl context. We will give you native access to
+ * root planet class.
+ */
+ enum ossimPlanet_ContextType
+ {
+ ossimPlanet_NOVIEWER_CONTEXT = 0,
+ ossimPlanet_PLANET_ONLY_CONTEXT = 1,
+ ossimPlanet_VIEWER_CONTEXT = 2
+ };
+ enum ossimPlanet_BOOL
+ {
+ ossimPlanet_FALSE = 0,
+ ossimPlanet_TRUE = 1
+ };
+
+ enum ossimPlanetFragShaderType
+ {
+ ossimPlanet_NO_SHADER = 0,
+ ossimPlanet_TOP,
+ ossimPlanet_REFERENCE,
+ ossimPlanet_OPACITY,
+ ossimPlanet_HORIZONTAL_SWIPE,
+ ossimPlanet_VERTICAL_SWIPE,
+ ossimPlanet_BOX_SWIPE,
+ ossimPlanet_CIRCLE_SWIPE,
+ ossimPlanet_ABSOLUTE_DIFFERENCE,
+ ossimPlanet_FALSE_COLOR_REPLACEMENT
+ };
+
+# define ossimPlanet_INVALID_INDEX ((ossimPlanet_IndexType)-1)
+ /******************************** Setup and Initialization API *****************************/
+
+ /**
+ * Add the passed in path to OpenSceneGraph's Library path. This will be used mainly for finding OpenSceneGraph
+ * plugins. If this needs to be setup it should be done before you call ossimPlanet_init and start adding layers
+ * to planet.
+ *
+ * @param path Path to add to the Library search path.
+ * @param insertFrontFlag Inserts the path to the front of the search path list if its ossimPlanet_TRUE and
+ * appends to the end otherwise.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addOpenSceneGraphLibraryPath(ossimPlanet_ConstStringType path,
+ ossimPlanet_BOOL insertFrontFlag);
+
+ /**
+ * Adds the passed in path to OpenSceneGraph's data path. This allows one to give relative path naming to
+ * data that is loaded. For example: if you have a font called arial.ttf and it's located in /fonts then you can add
+ * /fonts to the search path and you can load a font by just the name "arial.ttf". The /fonts will be prepended. If
+ * this needs to be setup it should be done before you call ossimPlanet_init and start adding layers to planet.
+ *
+ * @param path Path to add to the Data search path.
+ * @param insertFrontFlag Inserts the path to the front of the search path list if its ossimPlanet_TRUE and
+ * appends to the end otherwise.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addOpenSceneGraphDataPath(ossimPlanet_ConstStringType path,
+ ossimPlanet_BOOL insertFrontFlag);
+
+ /**
+ * Loads an ossim preference file.
+ *
+ * @param preferenceFile The preference file to load.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_loadOssimPreferenceFile(ossimPlanet_ConstStringType preferenceFile);
+
+ /**
+ * This is a utility call that allows one to set preference variables directly. This will allow one to
+ * modify preference variables. If this needs to be setup it should be done before you call ossimPlanet_init
+ * and start adding layers to planet.
+ *
+ * @param name The name of the preference variable.
+ * @param value The value of the preference variable.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setOssimPreferenceNameValue(ossimPlanet_ConstStringType name,
+ ossimPlanet_ConstStringType value);
+
+ /**
+ * Adds an ossim core plugin. If this is a directory then all files in the directoy that are plugins are added
+ *
+ * @param path Path to add to the OSSIM Plugin search path.
+ * @param insertFrontFlag Inserts the path to the front of the search path list if its ossimPlanet_TRUE and
+ * appends to the end otherwise.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addOssimPlugin(ossimPlanet_ConstStringType path,
+ ossimPlanet_BOOL insertFrontFlag);
+
+
+ /**
+ * Add elevation to the OSSIM core system.
+ *
+ * @param path Path to add to the Elevation.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addOssimElevation(ossimPlanet_ConstStringType path);
+
+ /**
+ *
+ * Elevation data is typically relative to mean sea level. The geoid grids will be used to shift the Mean Sea Level
+ * to ellipsoidal heights.
+ *
+ * @param path Path to add to the Geoid search path.
+ * @param byteOrder. Most of the goid grids don't have Endian indication. You can download little endian or big endian type geoid grids
+ * The basic 96 grid that comes with OSSIM egm96.grd is a big endian byte order. You can downlod from
+ * @param insertFrontFlag Inserts the path to the front of the search path list if its ossimPlanet_TRUE and
+ * appends to the end otherwise.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addGeoid(ossimPlanet_ConstStringType path,
+ ossimByteOrder byteOrder,
+ ossimPlanet_BOOL insertFrontFlag);
+
+ /**
+ * Used to initialize the system. This is typically called one time. It initializes internal registries.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_init();
+
+ /**
+ * Allows one to init by passing command line arguments. This is typically used by command line
+ * applications.
+ *
+ * @param argc A pointer to an integer.
+ * @param argv Pointer to the argv.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_initWithArgs(int* argc, char** argv[]);
+
+ /**
+ * Allows you to set the trace on and off for various classes in the system. This is in the format of a
+ * regular expression. Some of the special characters found in the regular expression are:
+ * ^ Matches at beginning of a line
+ * $ Matches at end of a line
+ * . Matches any single character
+ * [ ] Matches any character(s) inside the brackets
+ * [^ ] Matches any character(s) not inside the brackets
+ * - Matches any character in range on either side of a dash
+ * * Matches preceding pattern zero or more times
+ * + Matches preceding pattern one or more times
+ * ? Matches preceding pattern zero or once only
+ *
+ * () Saves a matched expression and uses it in a later match
+ *
+ * If you want to trace all
+ * ossim classes then do :
+ *
+ * ossimPlanet_setTracePattern("ossim.*");
+ *
+ * @param pattern A regular expression pattern to describe what to trace.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setTracePattern(ossimPlanet_ConstStringType pattern);
+
+ /**
+ * This is called to do any cleanup of the library.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_finalize();
+
+ /**
+ * Gives access to a microsecond sleep.
+ *
+ * @param microSeconds Specify how many microseconds to sleep.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_microSecondSleep(ossimPlanet_SizeType microSeconds);
+
+ /**
+ * Gives access to a millisecond sleep.
+ *
+ * @param milliSeconds Specify how many milli seconds to sleep.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_milliSecondSleep(ossimPlanet_SizeType milliSeconds);
+
+ /**
+ * Gives access to a seconds sleep.
+ *
+ * @param seconds Specify how many seconds to sleep.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_secondSleep(ossimPlanet_SizeType seconds);
+
+ /********************** DO STATE INTERFACE ***********************/
+
+ /**
+ * This will return an internal class that contains all the needed
+ * state information. It will basically create a self contained manager for
+ * view, layers, manipulator, ... etc.
+ *
+ * Note: Currently there can be only 1 view assigned per state. Once the state is called you can create view, layers
+ * add manipulator, ...etc for the given state.
+ *
+ * @param contextType This specifies the type of context you would like to create. @see ossimPlanet_contextType.
+ *
+ * @return State handle;
+ */
+ OSSIMPLANET_DLL ossimPlanet_StatePtr ossimPlanet_newState(ossimPlanet_ContextType type);
+
+ /**
+ * ossimPlanet_deleteState()
+ *
+ * Will delete the passed in state.
+ *
+ * @param state This is the state to delete.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_deleteState(ossimPlanet_StatePtr state);
+
+
+ /********************* ACCESS TO NATIVE POINTERS *********************/
+
+ /**
+ * This will be mainly used in native C++ that wants to add callbacks to get direct feedback from
+ * various actions that occur within planet. People should be able to do reinterpret_cast<ossimPlanet*> on
+ * the native pointer returned.
+ *
+ * @return Returns the address of the ossimPlanet object.
+ */
+ OSSIMPLANET_DLL ossimPlanet_PlanetPtr ossimPlanet_getNativePlanetPointer(ossimPlanet_StatePtr state);
+
+ /************************************ API FOR THE VIEW ********************************/
+
+ /**
+ * Allows one to disable the texture shaders.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setLandFragShaderType(ossimPlanet_StatePtr state,
+ ossimPlanetFragShaderType type);
+
+ /**
+ *
+ * When initially setting up your scene it is not set to the root Scene view or viewer. This only has affect in ossimPlanet_NOVIEWER_CONTEXT
+ * and ossimPlanet_VIEWER_CONTEXT where you have a Scene managers and manipulators.
+ *
+ * @param state The state to modify.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setSceneDataToView(ossimPlanet_StatePtr state);
+
+ /**
+ * Only support ossimPlanetManipulator type for now.
+ *
+ * @param state The state to modify.
+ * @param typeName The type of Manipulator to create. The current one is ossimPlanetManipulator.
+ * @param receverPathName The recever path name given to this object. We can pass setup commands to it.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewManipulator(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType typeName,
+ ossimPlanet_ConstStringType receiverPathName);
+ /**
+ * This will assume that a Gl context is created and that the Viewport is set. It will use
+ * GL calls to get the current Viewport values and set to the internal structures associated
+ * with the passed in state. This is used when you are manipulating the Viewport through
+ * GL calls. If this is the case then you can call this before rendering the planet.
+ *
+ * @param state State to modify.
+ */
+ OSSIMPLANET_DLL void setViewportToCurrentGlSettings(ossimPlanet_StatePtr state);
+
+
+ /**
+ * This will assume that a Gl context is created and that the Projection Matrix is set. It will use
+ * GL calls to get the current Projection Matrix values and set to the internal structures associated
+ * with the passed in state. This is used when you are manipulating the Projection Matrix through
+ * GL calls. If this is the case then you can call this before rendering the planet.
+ *
+ * @param state State to modify.
+ */
+ OSSIMPLANET_DLL void setProjectionMatrixToCurrentGlSettings(ossimPlanet_StatePtr state);
+
+ /**
+ * This will assume that a Gl context is created and that the ModelView Matrix is set. It will use
+ * GL calls to get the current ModelView Matrix values and set to the internal structures associated
+ * with the passed in state. This is used when you are manipulating the ModelView Matrix through
+ * GL calls. If this is the case then you can call this before rendering the planet.
+ *
+ * @param state State to modify.
+ */
+ OSSIMPLANET_DLL void setModelViewMatrixToCurrentGlSettings(ossimPlanet_StatePtr state);
+
+
+ /***** DO PROJECTION MATRIX INTERFACE *****/
+
+ /**
+ * This allows one to set the perspective.
+ *
+ * @param state The state to modify.
+ * @param fov Field of view in degrees.
+ * @param aspectRatio The aspect ratio of the view.
+ * @param near The near plane distance.
+ * @param far The far plane distance.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setProjectionMatrixAsPerspective(ossimPlanet_StatePtr state,
+ double fov,
+ double aspectRatio,
+ double near,
+ double far);
+
+ /**
+ * This is identical to the glFrustum settings.
+ *
+ * @param state The state to modify.
+ * @param left Left value.
+ * @param right Right value.
+ * @param bottom Bottom value.
+ * @param top Top value.
+ * @param zNear zNear value.
+ * @param zFar zFar value.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setProjectionMatrixAsFrustum(ossimPlanet_StatePtr state,
+ double left, double right,
+ double bottom, double top,
+ double zNear, double zFar);
+
+ /**
+ * This is identical to the glOrtho call and creates and orthographic projection.
+ *
+ * @param state The state to modify.
+ * @param left Left value.
+ * @param right Right value.
+ * @param bottom Bottom value.
+ * @param top Top value.
+ * @param zNear zNear value.
+ * @param zFar zFar value.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setProjectionMatrixAsOrtho(ossimPlanet_StatePtr state,
+ double left, double right,
+ double bottom, double top,
+ double zNear, double zFar);
+
+ /**
+ *
+ * Set to a 2D orthographic projection. See OpenGL glOrtho2D documentation for further details.
+ * @param state The state to modify.
+ * @param left Left value.
+ * @param right Right value.
+ * @param bottom Bottom value.
+ * @param top Top value.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setProjectionMatrixAsOrtho2D(ossimPlanet_StatePtr state,
+ double left, double right,
+ double bottom, double top);
+ /**
+ * This assumes a 4x4 array or 16 consecutive values. The values are stored row ordered.
+ * This means that the first 4 values are for the first row and the second four values are
+ * for the second row, ... etc.
+ *
+ * @param m The array of 16 values
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setProjectionMatrixAsRowOrderedArray(ossimPlanet_StatePtr state,
+ double* m);
+
+ /**
+ * This will set the projection matrix to the passed in values. Note m00 - m03 identifies the
+ * first row of the matrix, then the next is the second row, ... etc.
+ *
+ * @param state The state to modify the view orientation matrix.
+ * @param m00 row 0 col 0
+ * @param m01 row 0 col 1
+ * @param m02 row 0 col 2
+ * @param m03 row 0 col 3
+ * @param m10 row 1 col 0
+ * @param m11 row 1 col 1
+ * @param m12 row 1 col 2
+ * @param m13 row 1 col 3
+ * @param m20 row 2 col 0
+ * @param m21 row 2 col 1
+ * @param m22 row 2 col 2
+ * @param m23 row 2 col 3
+ * @param m30 row 3 col 0
+ * @param m31 row 3 col 1
+ * @param m32 row 3 col 2
+ * @param m33 row 3 col 3
+ *
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setProjectionMatrix(ossimPlanet_StatePtr state,
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33);
+ /****** NOW EXPOSE ORIENTATION MATRIX DEFINITIONS ****/
+
+ /**
+ * This allows one to pass in the lat, lon height and the euler angles to define the view matrix.
+ * The Euler angles are relative to the tangent plane at the given lat lon position. Note this is
+ * for the camera and the Z-Axis is the plumb/Nadir axis. This means that a heading, pitch and roll of all
+ * 0 degrees will have the eye looking straight down.
+ *
+ * Note: all lat lon values are assumed to be relative to the WGS84 ellipsoid.
+ *
+ * @param state The state to modify.
+ * @param lat The latitude of the view camera in degrees.
+ * @param lon The longitude of the view camera in degrees.
+ * @param height The height of the view camera in meters relative to the WGS84 ellipsoid.
+ * @param heading The heading of the view camera in degrees.
+ * @param pitch The pitch of the view camera in degrees.
+ * @param roll The roll of the view camera in degrees.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewMatrixAsLlhHprRelativeTangent(ossimPlanet_StatePtr state,
+ double lat,
+ double lon,
+ double height,
+ double heading,
+ double pitch,
+ double roll);
+
+ /**
+ * This allows one to pass in the lat, lon height and the euler angles to define the view matrix.
+ * The Euler angles are not relative to the tangent plane at the given lat lon position but instead the unit axis is used.
+ * for the camera and the Z-Axis is the plumb/Nadir axis.
+ *
+ * Note: all lat lon values are assumed to be relative to the WGS84 ellipsoid.
+ *
+ * @param state The state to modify.
+ * @param lat The latitude of the view camera in degrees.
+ * @param lon The longitude of the view camera in degrees.
+ * @param height The height of the view camera in meters relative to the WGS84 ellipsoid.
+ * @param heading The heading of the view camera in degrees.
+ * @param pitch The pitch of the view camera in degrees.
+ * @param roll The roll of the view camera in degrees.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewMatrixAsLlhHprAbsolute(ossimPlanet_StatePtr state,
+ double lat,
+ double lon,
+ double height,
+ double heading,
+ double pitch,
+ double roll);
+
+ /**
+ * This Will set the matrix as a row ordered array.
+ *
+ * @param state The state to modify the view orientation matrix.
+ * @param m Row ordered view matrix.
+ *
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewMatrixAsRowOrderedArray(ossimPlanet_StatePtr state,
+ const double *m);
+
+ /**
+ * This will set the matrix to the passed in values. Note m00 - m03 identifies the
+ * first row of the matrix, then the next is the second row, ... etc.
+ *
+ * @param state The state to modify the view orientation matrix.
+ * @param m00 row 0 col 0
+ * @param m01 row 0 col 1
+ * @param m02 row 0 col 2
+ * @param m03 row 0 col 3
+ * @param m10 row 1 col 0
+ * @param m11 row 1 col 1
+ * @param m12 row 1 col 2
+ * @param m13 row 1 col 3
+ * @param m20 row 2 col 0
+ * @param m21 row 2 col 1
+ * @param m22 row 2 col 2
+ * @param m23 row 2 col 3
+ * @param m30 row 3 col 0
+ * @param m31 row 3 col 1
+ * @param m32 row 3 col 2
+ * @param m33 row 3 col 3
+ *
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewMatrix(ossimPlanet_StatePtr state,
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33);
+
+ /*** NOW EXPOSE VIEWPORT DEFINITIONS *******/
+
+ /**
+ * ossimPlanet_setViewport
+ *
+ * Sets the viewport of the for the view of the passed in state.
+ *
+ * @param state The state to modify the viewport definitions.
+ * @param x The x location in pixels of the viewport. Typically 0
+ * @param y The y location in pixels of the viewport. Typically 0
+ * @param w The width in pixels of the viewport.
+ * @param h The height in pixels of the viewport.
+ *
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewport(ossimPlanet_StatePtr state,
+ int x,
+ int y,
+ int w,
+ int h);
+
+ /**
+ * Sets the color used to clear the viewport area.
+ *
+ * @param state The state information to modify the clear color.
+ * @param red The red component of the clear color.
+ * @param green The green component of the clear color.
+ * @param blue The blue component of the clear color.
+ * @param alpha The alpha component of the clear color.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setViewportClearColor(ossimPlanet_StatePtr state,
+ float red,
+ float green,
+ float blue,
+ float alpha);
+
+
+ /**
+ * Save the gl attributes. This is mainly only used if you are embedding in
+ * a non Open scenegraph application and you need the state attributes to be preserved
+ * after calling the ossimPlanet_frame.
+ *
+ * This will preserve the Matrix stacks (MODEL, TEXTURE, PROJECTION) and the
+ * GL_ALL_ATTRIB_BITS. After the call to frame then you should call
+ * ossimPlanet_popState();
+ */
+ OSSIMPLANET_DLL void ossimPlanet_pushState();
+
+ /**
+ * @see ossimPlanet_pushState();
+ */
+ OSSIMPLANET_DLL void ossimPlanet_popState();
+
+ OSSIMPLANET_DLL void ossimPlanet_setStateReceiverPathName(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType path);
+ OSSIMPLANET_DLL void ossimPlanet_setPlanetReceiverPathName(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType path);
+
+
+ /*************************** General Layer interfaces *********************/
+
+ /**
+ * This adds a layer to planet. the layer type is used in the ossimPlanetLayerRegistry
+ * to construct a layer of the passed layerType. The receiverName is used to set the receiver
+ * name of the layer created so action messages can be routed to it.
+ *
+ * @param state The state to modify.
+ * @param layerType Layer type name to add. This is used by the layer registry to construct a layer
+ * specified by the layerType.
+ * @param name This is the name you wish to give the layer.
+ * @param id This is the id for the layer.
+ * @param description This is the description for the layer.
+ * @param receiverPathName Allows one to create a receiver name for the layer. This is the target name for
+ * Action messages(@see ossimPlanet_routeAction).
+ *
+ * @return The natve pointer to the layer added.
+ */
+ OSSIMPLANET_DLL ossimPlanet_LayerPtr ossimPlanet_addLayer(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType layerType,
+ ossimPlanet_ConstStringType name,
+ ossimPlanet_ConstStringType id,
+ ossimPlanet_ConstStringType description,
+ ossimPlanet_ConstStringType receiverPathName);
+
+ OSSIMPLANET_DLL void ossimPlanet_removeLayerGivenPtr(ossimPlanet_StatePtr state,
+ ossimPlanet_LayerPtr layerPtr);
+ /**
+ * @param state The state to use.
+ *
+ * @return Returns the number of layers defined in planet for the give state.
+ */
+ OSSIMPLANET_DLL ossimPlanet_SizeType ossimPlanet_getNumberOfLayers(ossimPlanet_StatePtr state);
+
+ /**
+ * @param state The state to use.
+ * @param layerPtr The layer pointer to use.
+ *
+ * @return Returns the index of the layer given it's pointer.
+ */
+ OSSIMPLANET_DLL ossimPlanet_IndexType ossimPlanet_getIndexOfLayerGivenPtr(ossimPlanet_StatePtr state,
+ ossimPlanet_LayerPtr layerPtr);
+
+ /**
+ * @param state The state to use.
+ * @param idx The index number of the layer to return.
+ *
+ * @return Returns the layer pointer given an index. NULL or 0 is returned if idx is out of range.
+ */
+ OSSIMPLANET_DLL ossimPlanet_LayerPtr ossimPlanet_getLayerGivenIndex(ossimPlanet_StatePtr state,
+ ossimPlanet_IndexType idx);
+
+ /**
+ * @param state The state to use.
+ * @param idThe id of the layer to search.
+ *
+ * @return Returns the layer pointer identified by id.
+ */
+ OSSIMPLANET_DLL ossimPlanet_LayerPtr ossimPlanet_getLayerGivenId(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType id);
+ /**
+ * @param state The state to use.
+ * @param idx The index of the layer to access.
+ *
+ * @return The layer name for the layer at the specified index.
+ */
+ OSSIMPLANET_DLL ossimPlanet_ConstStringType ossimPlanet_getLayerName(ossimPlanet_LayerPtr layer);
+
+ /**
+ * @param layer The layer to set.
+ * @param name The name to set the layer to.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setLayerName(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType name);
+
+ /**
+ * @param state The state to use.
+ * @param idx The index of the layer to access.
+ *
+ * @return The layer name for the layer at the specified index.
+ */
+ OSSIMPLANET_DLL ossimPlanet_ConstStringType ossimPlanet_getLayerId(ossimPlanet_LayerPtr layer);
+
+ /**
+ * @param layer The layer to set.
+ * @param id The id to set the layer to.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setLayerId(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType id);
+
+ /**
+ * @param state The state to use.
+ * @param idx The index of the layer to access.
+ *
+ * @return The layer description for the layer at the specified index.
+ */
+ OSSIMPLANET_DLL ossimPlanet_ConstStringType ossimPlanet_getLayerDescription(ossimPlanet_LayerPtr layer);
+
+ /**
+ * @param layer The layer to set.
+ * @param description The description to set the layer to.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setLayerDescription(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType description);
+
+ /**
+ * @param state The state to use.
+ * @param idx The index of the layer to access.
+ *
+ * @return The recever path name for the layer at the specified index.
+ */
+ OSSIMPLANET_DLL ossimPlanet_ConstStringType ossimPlanet_getLayerReceverPathName(ossimPlanet_LayerPtr layer);
+
+ /**
+ * @param layer The layer to set.
+ * @param receiverName The description to set the layer to.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setLayerReceiverPathName(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType receiverPathName);
+
+
+ /**
+ * @param state The state to use.
+ * @param idx The index of the layer to access.
+ *
+ * @return The layer enable flag for the layer at the specified index.
+ */
+ OSSIMPLANET_DLL ossimPlanet_BOOL ossimPlanet_getLayerEnableFlag(ossimPlanet_LayerPtr layer);
+
+ /**
+ *
+ * @param layer The layer to set.
+ * @param flag This specifies if the layer is enabled or not. A value of ossimPlanet_TRUE will
+ * enable the layer and a value of ossimPlanet_FALSE will disable the layer.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_setLayerEnableFlag(ossimPlanet_LayerPtr layer,
+ ossimPlanet_BOOL flag);
+
+
+ /**
+ *
+ * Adds an image to the reference layer. Note: location is currently for local data and cann be a directory or
+ * a file. We currently do not recurse directories so if the passed in file is a directory no subdirectories will be scanned.
+ *
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addImageToReceiver(ossimPlanet_ConstStringType location,
+ ossimPlanet_ConstStringType receverName,
+ ossimPlanet_BOOL addInTheBackgroundFlag);
+
+ /**
+ * This is for legacy KWL support and is only for texture layers.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_addTextureLayersFromKwlFile(ossimPlanet_StatePtr state,
+ const char* kwlFile);
+
+ /******************************* Action Routing Interface****************************/
+ /**
+ * This will use ossimPlanet's Action router to route the message to the destination. For example: lets say
+ * we have a receiver name as foo and we have an action called Set.
+ *
+ * ossimPlanet_routeActionForm1("<Set target=":foo">.....</Set>);
+ *
+ * This will route a action "Set" to the receiver "foo".
+ *
+ * @param action
+ */
+ OSSIMPLANET_DLL void ossimPlanet_executeXmlAction(ossimPlanet_ConstStringType completeAction);
+
+ /**
+ * Will post the action to a threaded action queue so it executes in the background.
+ */
+ OSSIMPLANET_DLL void ossimPlanet_postXmlAction(ossimPlanet_ConstStringType completeAction);
+
+ /**************************** Rendering Interfaces ***********************************/
+
+ /**
+ * This is the main rendering step. This will render 1 frame.
+ * @param state The state to modify.
+ *
+ * @return Returns ossimPlanet_TRUE if the render frame can continue again or
+ * ossimPlanet_FALSE if it was canceled. This is typically only important for ossimPlanet_VIEWER type
+ * context.
+ */
+ OSSIMPLANET_DLL ossimPlanet_BOOL ossimPlanet_renderFrame(ossimPlanet_StatePtr state);
+
+ /**
+ * This is the main rendering step. This will render 1 frame and preserve the state. This will
+ * call osismPlanet_pushState before rendering and ossimPlanet_popState after rendering and will preserve
+ * gl attributes, View, Projection and Texture matrices.
+ *
+ * @param state The state to modify.
+ *
+ * @return Returns ossimPlanet_TRUE if the render frame can continue again or
+ * ossimPlanet_FALSE if it was canceled. This is typically only important for ossimPlanet_VIEWER type
+ * context.
+ */
+ OSSIMPLANET_DLL ossimPlanet_BOOL ossimPlanet_renderFramePreserveState(ossimPlanet_StatePtr state);
+
+ /**
+ * This is used determine if another frame is required to be rendered. Call this before
+ * you call ossimPlanet_Frame.
+ *
+ * <pre>
+ * if(ossimPlanet_needsRendering(state))
+ * {
+ * ossimPlanet_renderFrame(state);
+ * }
+ * </pre>
+ *
+ * @param state The state to modify.
+ * @return ossimPlanet_TRUE if needs to continue rendering or ossimPlanet_FALSE if
+ * no more rendering is required.
+ */
+ OSSIMPLANET_DLL ossimPlanet_BOOL ossimPlanet_needsRendering(ossimPlanet_StatePtr state);
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // end ossimPlanetViewApi_HEADER
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetArchive.h b/ossimPlanet/include/ossimPlanet/ossimPlanetArchive.h
new file mode 100755
index 0000000..59ee4dd
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetArchive.h
@@ -0,0 +1,37 @@
+
+#ifndef ossimPlanetArchive_HEADER
+#define ossimPlanetArchive_HEADER
+
+#include <vector>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimFilename.h>
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ScopedLock>
+#include <ossimPlanet/ossimPlanetArchiveMapping.h>
+
+
+class OSSIMPLANET_DLL ossimPlanetArchive : public osg::Referenced
+{
+private:
+ bool useArchiveMapping;
+ std::vector<ossimPlanetArchiveMapping> mappingList;
+ mutable ossimPlanetReentrantMutex theArchiveMutex;
+
+public:
+ ossimPlanetArchive();
+protected:
+ ~ossimPlanetArchive();
+
+public:
+ void addMapping(ossimPlanetArchiveMapping &mapping);
+ void removeMapping(ossimPlanetArchiveMapping &mapping);
+ ossimFilename matchPath(const ossimFilename &filename);
+ ossimFilename convertToDirectory(ossimFilename &filename);
+ void setArchiveMappingEnabledFlag(bool enabled = false);
+ bool archiveMappingEnabled();
+ std::vector<ossimPlanetArchiveMapping> getMappingList();
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetArchiveMapping.h b/ossimPlanet/include/ossimPlanet/ossimPlanetArchiveMapping.h
new file mode 100755
index 0000000..aca687f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetArchiveMapping.h
@@ -0,0 +1,29 @@
+#ifndef ossimPlanetArchiveMapping_HEADER
+#define ossimPlanetArchiveMapping_HEADER
+
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimFilename.h>
+
+
+class OSSIMPLANET_DLL ossimPlanetArchiveMapping
+{
+private:
+ ossimFilename src;
+ ossimFilename dest;
+
+public:
+ ossimPlanetArchiveMapping();
+ ossimPlanetArchiveMapping(const ossimFilename &source, const ossimFilename &destination);
+ ~ossimPlanetArchiveMapping();
+
+ ossimFilename getSource();
+ void setSource(const ossimFilename &source);
+
+ ossimFilename getDestination();
+ void setDestination(const ossimFilename &destination);
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetBillboardIcon.h b/ossimPlanet/include/ossimPlanet/ossimPlanetBillboardIcon.h
new file mode 100644
index 0000000..de00845
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetBillboardIcon.h
@@ -0,0 +1,75 @@
+#ifndef ossimPlanetBillboardIcon_HEADER
+#define ossimPlanetBillboardIcon_HEADER
+#include <osg/Node>
+#include <osg/NodeVisitor>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <osg/Billboard>
+#include <osg/MatrixTransform>
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossimPlanet/ossimPlanetIconGeom.h>
+
+class ossimPlanetBillboardIcon :public osg::Node
+{
+public:
+ class ossimPlanetBillboardIconUpdateCallback : public osg::NodeCallback
+ {
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ ossimPlanetBillboardIcon* n = dynamic_cast<ossimPlanetBillboardIcon*>(node);
+ if(n)
+ {
+ n->traverse(*nv);
+ }
+ }
+ };
+ /**
+ * The normalization factor is used to scale the bill board into the units of
+ * the scenegraph. This is done by the billboard transform. This transform is wrapped
+ * with a fudge factor transform to make sure that the icon stays on top of the terrain
+ */
+ ossimPlanetBillboardIcon(double objectGroundSize = 50000.0/OSSIMPLANET_WGS_84_RADIUS_EQUATOR);
+ void setGroundObjectSize(double groundSize);
+ void setIcon(osg::ref_ptr<osg::Image> img);
+ void setIcon(osg::ref_ptr<osg::Texture2D> img);
+ osg::ref_ptr<ossimPlanetIconGeom> getGeom()
+ {
+ return theGeom.get();
+ }
+ void setGeom(osg::ref_ptr<ossimPlanetIconGeom> geom);
+ /**
+ * This turns on auto scaling so that the full texture size is reached once
+ * the gsd is approximately the passed in meters per pixel.
+ */
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual osg::BoundingSphere computeBound() const;
+ bool isCulled()const;
+ void setMinPixelSize(ossim_uint32 size)
+ {
+ theMinPixelSize = size;
+ }
+ void setMaxPixelSize(ossim_uint32 size)
+ {
+ theMaxPixelSize = size;
+ }
+protected:
+ osg::Billboard* theBillboard;
+ osg::ref_ptr<ossimPlanetIconGeom> theGeom;
+ osg::ref_ptr<osg::MatrixTransform> theBillboardTransform;
+ osg::ref_ptr<osg::MatrixTransform> theFudgeFactorTransform;
+ osg::ref_ptr<osg::MatrixTransform> theLabelTransform;
+ osg::Matrixd theFudgeFactorMatrix;
+ bool theNeedsUpdateFlag;
+ bool theCulledFlag;
+ ossim_uint32 theMinPixelSize;
+ ossim_uint32 theMaxPixelSize;
+ ossim_uint32 thePixelWidth;
+ ossim_uint32 thePixelHeight;
+ osg::Vec3d theTranslate;
+
+ bool theScaleFactorChangedFlag;
+ ossim_float64 theScaleFactor;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetBoundingBox.h b/ossimPlanet/include/ossimPlanet/ossimPlanetBoundingBox.h
new file mode 100644
index 0000000..518b269
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetBoundingBox.h
@@ -0,0 +1,234 @@
+#ifndef ossimPlanetBoundingBox_HEADER
+#define ossimPlanetBoundingBox_HEADER
+#include <osg/Referenced>
+#include <osg/Polytope>
+#include <osg/CullSettings>
+#include <vector>
+#include <ossim/base/ossimCommon.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/mkUtils.h>
+
+class OSSIMPLANET_DLL ossimPlanetBoundingBox : public osg::Referenced
+{
+public:
+ ossimPlanetBoundingBox()
+ :osg::Referenced()
+ {
+ theCorners[0] = osg::Vec3d(0,0,0);
+ theCorners[1] = osg::Vec3d(0,0,0);
+ theCorners[2] = osg::Vec3d(0,0,0);
+ theCorners[3] = osg::Vec3d(0,0,0);
+ theCorners[4] = osg::Vec3d(0,0,0);
+ theCorners[5] = osg::Vec3d(0,0,0);
+ theCorners[6] = osg::Vec3d(0,0,0);
+ theCorners[7] = osg::Vec3d(0,0,0);
+
+ theCenter = osg::Vec3d(0,0,0);
+ theRadius = 0.0;
+ }
+ ossimPlanetBoundingBox(const osg::Vec3d &p0,
+ const osg::Vec3d &p1,
+ const osg::Vec3d &p2,
+ const osg::Vec3d &p3,
+ const osg::Vec3d &p4,
+ const osg::Vec3d &p5,
+ const osg::Vec3d &p6,
+ const osg::Vec3d &p7)
+ :osg::Referenced()
+ {
+ theCorners[0] = p0;
+ theCorners[1] = p1;
+ theCorners[2] = p2;
+ theCorners[3] = p3;
+ theCorners[4] = p4;
+ theCorners[5] = p5;
+ theCorners[6] = p6;
+ theCorners[7] = p7;
+
+ theCenter = (p0+p1+p2+p3+p4+p5+p6+p7)*(1.0/8.0);
+ computeRadius();
+ }
+ ossimPlanetBoundingBox(const ossimPlanetBoundingBox& src)
+ :osg::Referenced()
+ {
+ theCorners[0] = src.theCorners[0];
+ theCorners[1] = src.theCorners[1];
+ theCorners[2] = src.theCorners[2];
+ theCorners[3] = src.theCorners[3];
+ theCorners[4] = src.theCorners[4];
+ theCorners[5] = src.theCorners[5];
+ theCorners[6] = src.theCorners[6];
+ theCorners[7] = src.theCorners[7];
+ theCenter = src.theCenter;
+ theRadius = src.theRadius;
+ }
+ // note the distance is a 2d vector. the distance[0]
+ // is the distance to extrude the points in the direction
+ // of the normal and the distance[1] is the distance along
+ // the reflected direction.
+ //
+ void extrude(const osg::Vec3d &p0,
+ const osg::Vec3d &p1,
+ const osg::Vec3d &p2,
+ const osg::Vec3d &p3,
+ const osg::Vec3d &outwardNormal,
+ const osg::Vec2d &distance)
+ {
+ theCorners[0] = p0 + outwardNormal*distance[1];
+ theCorners[1] = p1 + outwardNormal*distance[1];
+ theCorners[2] = p2 + outwardNormal*distance[1];
+ theCorners[3] = p3 + outwardNormal*distance[1];
+
+ theCorners[4] = p0 + outwardNormal*distance[0];
+ theCorners[5] = p1 + outwardNormal*distance[0];
+ theCorners[6] = p2 + outwardNormal*distance[0];
+ theCorners[7] = p3 + outwardNormal*distance[0];
+ theCenter = (theCorners[0]+
+ theCorners[1]+
+ theCorners[2]+
+ theCorners[3]+
+ theCorners[4]+
+ theCorners[5]+
+ theCorners[6]+
+ theCorners[7])*(1.0/8.0);
+ computeRadius();
+ }
+ void extrude(const osg::Vec3d& center,
+ const osg::Vec3d& up,
+ const osg::Vec3d& right,
+ const osg::Vec3d& normal,
+ const osg::Vec2d& distanceUp,
+ const osg::Vec2d& distanceRight,
+ const osg::Vec2d& distanceNormal)
+ {
+ // along negative normal
+ //ul, ur, lr, ll
+ theCorners[0] = center+((up*distanceUp[0])+
+ (right*distanceRight[1]) +
+ (normal*distanceNormal[1]));
+ theCorners[1] = center+((up*distanceUp[0])+
+ (right*distanceRight[0]) +
+ (normal*distanceNormal[1]));
+ theCorners[2] = center+((up*distanceUp[1])+
+ (right*distanceRight[0]) +
+ (normal*distanceNormal[1]));
+
+ theCorners[3] = center+((up*distanceUp[1])+
+ (right*distanceRight[1]) +
+ (normal*distanceNormal[1]));
+ // along positive normal
+ //ul, ur, lr, ll
+ theCorners[4] = center+((up*distanceUp[0])+
+ (right*distanceRight[1]) +
+ (normal*distanceNormal[0]));
+ theCorners[5] = center+((up*distanceUp[0])+
+ (right*distanceRight[0]) +
+ (normal*distanceNormal[0]));
+ theCorners[6] = center+((up*distanceUp[1])+
+ (right*distanceRight[0]) +
+ (normal*distanceNormal[0]));
+
+ theCorners[7] = center+((up*distanceUp[1])+
+ (right*distanceRight[1]) +
+ (normal*distanceNormal[0]));
+ theCenter = (theCorners[0]+
+ theCorners[1]+
+ theCorners[2]+
+ theCorners[3]+
+ theCorners[4]+
+ theCorners[5]+
+ theCorners[6]+
+ theCorners[7])*(1.0/8.0);
+ computeRadius();
+ }
+
+
+ osg::Vec3d& operator[](unsigned int idx)
+ {
+ return theCorners[idx];
+ }
+ const osg::Vec3d& operator[](unsigned int idx)const
+ {
+ return theCorners[idx];
+ }
+ bool intersects(const osg::Polytope& frustum)const;
+ bool isInFront(const osg::Vec3d& eye,
+ const osg::Vec3d& direction)const;
+
+
+ void transform(const osg::Matrix& m)
+ {
+ theCorners[0] = theCorners[0]*m,
+ theCorners[1] = theCorners[1]*m,
+ theCorners[2] = theCorners[2]*m,
+ theCorners[3] = theCorners[3]*m,
+ theCorners[4] = theCorners[4]*m,
+ theCorners[5] = theCorners[5]*m,
+ theCorners[6] = theCorners[6]*m,
+ theCorners[7] = theCorners[7]*m,
+ theCenter = (theCorners[0]+
+ theCorners[1]+
+ theCorners[2]+
+ theCorners[3]+
+ theCorners[4]+
+ theCorners[5]+
+ theCorners[6]+
+ theCorners[7])*(1.0/8.0);
+ theTopCenter = (theCorners[0]+
+ theCorners[1]+
+ theCorners[2]+
+ theCorners[3])*.25;
+ theBottomCenter = (theCorners[4]+
+ theCorners[5]+
+ theCorners[6]+
+ theCorners[7])*.25;
+ computeRadius();
+
+ }
+ void setCenter(const osg::Vec3d& center)
+ {
+ theCenter = center;
+ }
+ const osg::Vec3d& center()const
+ {
+ return theCenter;
+ }
+ double radius()const
+ {
+ return theRadius;
+ }
+ double groundRadius()const
+ {
+ return theGroundRadius;
+ }
+protected:
+ void computeRadius()
+ {
+ theRadius = ossim::max((theCorners[0]-theCenter).length(),
+ ossim::max((theCorners[1]-theCenter).length(),
+ ossim::max((theCorners[2]-theCenter).length(),
+ ossim::max((theCorners[3]-theCenter).length(),
+ ossim::max((theCorners[4]-theCenter).length(),
+ ossim::max((theCorners[5]-theCenter).length(),
+ ossim::max((theCorners[6]-theCenter).length(),
+ (theCorners[7]-theCenter).length())))))));
+ // this is a crude ground radius estimate that just takes the top
+ // Quad and Bottom quad and see who has the largest radius and takes the Max of that
+ theGroundRadius = ossim::max((theCorners[0]-theTopCenter).length(),
+ ossim::max((theCorners[1]-theTopCenter).length(),
+ ossim::max((theCorners[2]-theTopCenter).length(),
+ ossim::max((theCorners[3]-theTopCenter).length(),
+ ossim::max((theCorners[4]-theBottomCenter).length(),
+ ossim::max((theCorners[5]-theBottomCenter).length(),
+ ossim::max((theCorners[6]-theBottomCenter).length(),
+ (theCorners[7]-theBottomCenter).length())))))));
+ }
+ osg::Vec3d theCorners[8];
+ osg::Vec3d theCenter;
+ osg::Vec3d theTopCenter;
+ osg::Vec3d theBottomCenter;
+ double theRadius;
+ double theGroundRadius;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetCache.h b/ossimPlanet/include/ossimPlanet/ossimPlanetCache.h
new file mode 100644
index 0000000..cc406f6
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetCache.h
@@ -0,0 +1,178 @@
+#ifndef ossimPlanetCache_HEADER
+#define ossimPlanetCache_HEADER
+#include <osg/Referenced>
+#include <osg/Timer>
+#include <OpenThreads/ReentrantMutex>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <ossimPlanet/ossimPlanetTerrainTileId.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+#include <map>
+
+class OSSIMPLANET_DLL ossimPlanetImageCache : public osg::Referenced
+{
+public:
+ struct TileInfo
+ {
+ osg::Timer_t theTimeStamp;
+ osg::ref_ptr<ossimPlanetImage> theImage;
+ };
+ ossimPlanetImageCache()
+ :theCurrentCacheSize(0),
+ theMinCacheSize(0),
+ theMaxCacheSize(0),
+ theEnabledFlag(true)
+ {
+
+ }
+ virtual ~ossimPlanetImageCache()
+ {
+ }
+ void setEnabledFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theEnabledFlag = flag;
+ }
+ bool enabledFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return theEnabledFlag;
+ }
+ virtual void clean() = 0;
+ virtual void shrink()=0;
+ virtual void addOrUpdate(ossimPlanetImage* image)=0;
+ virtual ossimPlanetImage* get(const ossimPlanetTerrainTileId& id)=0;
+ virtual bool hasImage(const ossimPlanetTerrainTileId& id)const=0;
+
+ void setMinMaxCacheSizeInBytes(ossim_int64 minSize, ossim_int64 maxSize)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theMinCacheSize = minSize<maxSize?minSize:maxSize;
+ theMaxCacheSize = minSize>maxSize?minSize:maxSize;
+ }
+ void setMinMaxCacheSizeInMegaBytes(ossim_int64 minSize, ossim_int64 maxSize)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theMinCacheSize = minSize<maxSize?minSize:maxSize;
+ theMaxCacheSize = minSize>maxSize?minSize:maxSize;
+ theMinCacheSize *= static_cast<ossim_int64>(1024*1024);
+ theMaxCacheSize *= static_cast<ossim_int64>(1024*1024);
+ }
+ void setMinMaxCacheSizeInGigaBytes(ossim_int64 minSize, ossim_int64 maxSize)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theMinCacheSize = minSize<maxSize?minSize:maxSize;
+ theMaxCacheSize = minSize>maxSize?minSize:maxSize;
+ theMinCacheSize *= static_cast<ossim_int64>(1024*1024*1024);
+ theMaxCacheSize *= static_cast<ossim_int64>(1024*1024*1024);
+ }
+ ossim_int64 cacheSizeInBytes()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return theCurrentCacheSize;
+ }
+ ossim_int64 maxCacheSizeInBytes()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return theMaxCacheSize;
+ }
+ ossim_int64 minCacheSizeInBytes()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return theMinCacheSize;
+ }
+ bool exceedsMaxCacheSize()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return (theCurrentCacheSize>theMaxCacheSize);
+ }
+ bool exceedsMinCacheSize()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return (theCurrentCacheSize>theMinCacheSize);
+ }
+
+protected:
+ mutable OpenThreads::Mutex theMutex;
+ ossim_int64 theCurrentCacheSize;
+ ossim_int64 theMinCacheSize;
+ ossim_int64 theMaxCacheSize;
+ bool theEnabledFlag;
+};
+
+class OSSIMPLANET_DLL ossimPlanetMemoryImageCache : public ossimPlanetImageCache
+{
+public:
+ typedef std::map<ossimPlanetTerrainTileId, TileInfo> TileMap;
+ ossimPlanetMemoryImageCache()
+ :ossimPlanetImageCache()
+ {
+ }
+ virtual void clean()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theCurrentCacheSize = 0;
+ theTileCache.clear();
+ }
+ virtual void shrink();
+ virtual void addOrUpdate(ossimPlanetImage* image);
+ virtual ossimPlanetImage* get(const ossimPlanetTerrainTileId& id);
+ bool hasImage(const ossimPlanetTerrainTileId& id)const;
+
+protected:
+ TileMap theTileCache;
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetDiskImageCache : public ossimPlanetImageCache
+{
+public:
+ enum OutputType
+ {
+ DISK_CACHE_RAW = 0,
+ DISK_CACHE_JPEG
+ };
+ ossimPlanetDiskImageCache();
+ bool openDirectory(const ossimFilename& file, bool createIfNotExistsFlag=true);
+ virtual void clean();
+ virtual void shrink();
+ virtual void addOrUpdate(ossimPlanetImage* image);
+ virtual ossimPlanetImage* get(const ossimPlanetTerrainTileId& id);
+ bool hasImage(const ossimPlanetTerrainTileId& id)const;
+protected:
+ ossimFilename buildTileFile(const ossimPlanetTerrainTileId& id)const;
+ ossimFilename m_directory;
+ ossimFilename m_indexFile;
+ ossimKeywordlist m_indexFileKwl;
+ OutputType m_outputType;
+};
+
+class OSSIMPLANET_DLL ossimPlanetImageCacheShrinkOperation : public ossimPlanetOperation
+{
+public:
+ ossimPlanetImageCacheShrinkOperation()
+ :theCache(0)
+ {
+ }
+ virtual ~ossimPlanetImageCacheShrinkOperation()
+ {
+ theCache = 0;
+ }
+ void setCache(ossimPlanetImageCache* value)
+ {
+ theCache = value;
+ }
+ virtual void run()
+ {
+ if(theCache.valid())
+ {
+ theCache->shrink();
+ }
+ }
+protected:
+ osg::ref_ptr<ossimPlanetImageCache> theCache;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetCacheTextureLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetCacheTextureLayer.h
new file mode 100644
index 0000000..9ca8807
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetCacheTextureLayer.h
@@ -0,0 +1,79 @@
+#ifndef ossimPlanetCacheTextureLayer_HEADER
+#define ossimPlanetCacheTextureLayer_HEADER
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetCache.h>
+
+class OSSIMPLANET_DLL ossimPlanetCacheTextureLayer : public ossimPlanetTextureLayer
+{
+public:
+ ossimPlanetCacheTextureLayer();
+ ossimPlanetCacheTextureLayer(const ossimPlanetCacheTextureLayer& src);
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimString getClassName()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ void setTextureLayer(ossimPlanetTextureLayer* layer);
+ void setCache(ossimPlanetImageCache* cache);
+
+
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid);
+
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+
+ virtual const osg::ref_ptr<ossimPlanetLookAt> getLookAt()const;
+ virtual void setLookAt(osg::ref_ptr<ossimPlanetLookAt> lookAt);
+
+ virtual void getDateRange(ossimDate& minDate,
+ ossimDate& maxDate)const;
+ /**
+ * Approximate length in meters of the hypotneus. Just uses the getExtents
+ * and ten approximates a meter gsd from the degree bounds.
+ */
+ virtual double getApproximateHypotneusLength()const;
+
+ /**
+ * Will return the center lat lon and the approximate hypotneus length in meters.
+ */
+ virtual void getCenterLatLonLength(double& centerLat,
+ double& centerLon,
+ double& length)const;
+ virtual void setEnableFlag(bool flag);
+ virtual void setFilterType(const ossimString& filterType);
+ virtual void getMetadata(ossimRefPtr<ossimXmlNode> metadata)const;
+ virtual ossimRefPtr<ossimXmlNode> saveXml(bool recurseFlag=true)const;
+ virtual bool loadXml(ossimRefPtr<ossimXmlNode> node);
+ virtual void resetLookAt();
+
+ virtual ossimPlanetTextureLayer* findLayerByName(const ossimString& layerName,
+ bool recurseFlag=false);
+ virtual const ossimPlanetTextureLayer* findLayerByName(const ossimString& layerName,
+ bool recurseFlag=false)const;
+
+ virtual ossimPlanetTextureLayer* findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId);
+ virtual const ossimPlanetTextureLayer* findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId)const;
+
+ virtual ossimPlanetTextureLayer* findLayerById(const ossimString& layerId,
+ bool recurseFlag=false);
+ virtual const ossimPlanetTextureLayer* findLayerById(const ossimString& layerId,
+ bool recurseFlag=false)const;
+protected:
+ osg::ref_ptr<ossimPlanetTextureLayer> m_textureLayer;
+ osg::ref_ptr<ossimPlanetImageCache> m_cache;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetCallback.h b/ossimPlanet/include/ossimPlanet/ossimPlanetCallback.h
new file mode 100644
index 0000000..cdb64d7
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetCallback.h
@@ -0,0 +1,110 @@
+#ifndef ossimPlanetCallback_HEADER
+#define ossimPlanetCallback_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <OpenThreads/ScopedLock>
+#include <vector>
+class OSSIMPLANET_DLL ossimPlanetCallback : public osg::Referenced
+{
+public:
+ ossimPlanetCallback()
+ :theEnableFlag(true)
+ {}
+ void setEnableFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackMutex);
+ theEnableFlag = flag;
+ }
+ bool enableFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackMutex);
+ return theEnableFlag;
+ }
+protected:
+ mutable ossimPlanetReentrantMutex theCallbackMutex;
+ bool theEnableFlag;
+};
+
+template <class T>
+class ossimPlanetCallbackListInterface
+ {
+ public:
+ typedef std::vector<osg::ref_ptr<T> > CallbackListType;
+ ossimPlanetCallbackListInterface()
+ :theBlockCallbacksFlag(false)
+ {
+
+ }
+ virtual ~ ossimPlanetCallbackListInterface(){}
+ virtual void addCallback(T* callback)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(!hasCallbackNoMutex(callback))
+ {
+ theCallbackList.push_back(callback);
+ }
+ }
+ virtual void addCallback(osg::ref_ptr<T> callback)
+ {
+ addCallback(callback.get());
+ }
+ virtual void removeCallback(T* callback);
+ virtual void removeCallback(osg::ref_ptr<T> callback)
+ {
+ removeCallback(callback.get());
+ }
+ virtual void blockCallbacks(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ theBlockCallbacksFlag = flag;
+ }
+ bool hasCallback(const T* callback)const;
+ protected:
+ bool hasCallbackNoMutex(const T* callback)const;
+
+ mutable ossimPlanetReentrantMutex theCallbackListMutex;
+ CallbackListType theCallbackList;
+ bool theBlockCallbacksFlag;
+
+ };
+template <class T>
+void ossimPlanetCallbackListInterface<T>::removeCallback(T* callback)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ unsigned int idx;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx] == callback)
+ {
+ theCallbackList.erase(theCallbackList.begin() + idx);
+ break;
+ }
+ }
+}
+
+template <class T>
+bool ossimPlanetCallbackListInterface<T>::hasCallback(const T* callback)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ return hasCallbackNoMutex(callback);
+}
+
+template <class T>
+bool ossimPlanetCallbackListInterface<T>::hasCallbackNoMutex(const T* callback)const
+{
+ unsigned int idx;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx] == callback)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetClientThread.h b/ossimPlanet/include/ossimPlanet/ossimPlanetClientThread.h
new file mode 100644
index 0000000..f826dc4
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetClientThread.h
@@ -0,0 +1,94 @@
+#ifndef ossimPlanetClientThread_HEADER
+#define ossimPlanetClientThread_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossimPlanet/sg_socket.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include "ossimPlanetRefBlock.h"
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/sg_socket.h>
+#include <queue>
+#include <map>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+class OSSIMPLANET_DLL ossimPlanetClientConnection : public osg::Referenced
+{
+public:
+ ossimPlanetClientConnection(SGSocket* socket,
+ ossim_uint32 queueSize=1024);
+ ossimPlanetClientConnection();
+ virtual ~ossimPlanetClientConnection();
+
+ ossimString getHost()const;
+ ossimString getPortString()const;
+ ossimString getPortType()const;
+ void getConnection(ossimString& host,
+ ossimString& port,
+ ossimString& portType);
+ bool setConnection(const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType);
+
+ void addMessage(const ossimString& message);
+ void sendNextMessage();
+ bool hasMessages()const;
+ void clearQueue();
+
+ SGSocket* getSocket();
+ void setSocket(SGSocket* socket);
+
+protected:
+ ossimString popMessage();
+ mutable ossimPlanetReentrantMutex theMutex;
+ mutable ossimPlanetReentrantMutex theMessageQueueMutex;
+ SGSocket* theSocket;
+ ossim_uint32 theMaxQueueSize;
+ std::deque<ossimString> theMessageQueue;
+};
+
+class OSSIMPLANET_DLL ossimPlanetClientThread : public osg::Referenced,
+ public OpenThreads::Thread
+{
+
+public:
+
+ ossimPlanetClientThread();
+ virtual ~ossimPlanetClientThread();
+ virtual void run();
+ virtual int cancel();
+
+ /**
+ * creates a conneciton and returns the id
+ */
+ osg::ref_ptr<ossimPlanetClientConnection> newConnection(const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType);
+ bool setConnection(ossim_uint32 idx,
+ const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType);
+
+ void removeConnection(osg::ref_ptr<ossimPlanetClientConnection> connection);
+ osg::ref_ptr<ossimPlanetClientConnection> removeConnection(ossim_uint32 idx);
+ const osg::ref_ptr<ossimPlanetClientConnection> getConnection(ossim_uint32 idx)const;
+
+ void sendMessage(ossim_uint32 idx,
+ const ossimString& message);
+ void broadcastMessage(const ossimString& message);
+ ossim_uint32 getNumberOfConnections()const;
+
+
+ void updateClientThreadBlock();
+protected:
+ void protectedSendMessage(ossim_uint32 idx,
+ const ossimString& message);
+ void protectedUpdateClientThreadBlock();
+
+ typedef std::vector<osg::ref_ptr<ossimPlanetClientConnection> > ossimPlanetClientThreadConnectionList;
+ mutable ossimPlanetReentrantMutex theConnectionListMutex;
+ osg::ref_ptr<ossimPlanetRefBlock> theBlock;
+ bool theStartedFlag;
+ bool theDoneFlag;
+ ossimPlanetClientThreadConnectionList theClientConnectionList;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetCloudLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetCloudLayer.h
new file mode 100644
index 0000000..e66b823
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetCloudLayer.h
@@ -0,0 +1,231 @@
+#ifndef ossimPlanetCloudLayer_HEADER
+#define ossimPlanetCloudLayer_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <osg/NodeVisitor>
+#include <osg/TexMat>
+#include <osg/Geometry>
+#include <vector>
+#include <cstdlib>
+
+class OSSIMPLANET_DLL ossimPlanetCloudLayer : public ossimPlanetLayer
+{
+public:
+ typedef osg::ref_ptr<osg::Geometry> geometryPtr;
+ typedef std::vector<geometryPtr> geometryPtrArray;
+
+ class OSSIMPLANET_DLL Patch : public ossimPlanetGrid
+ {
+ public:
+ Patch(double deltaLat=1.0, double deltaLon=1.0)
+ :ossimPlanetGrid(GEODETIC_MODEL),
+ theDeltaLat(deltaLat),
+ theDeltaLon(deltaLon)
+ {
+ }
+ virtual void getRootIds(TileIds &ids)const
+ {
+ ids.push_back(ossimPlanetTerrainTileId());
+ }
+ virtual void centerModel(const ossimPlanetTerrainTileId& /* tileId */,
+ ModelPoint& modelPoint)
+ {
+ modelPoint = ModelPoint();
+ }
+ virtual void globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const
+ {
+ modelPoint.setX(-theDeltaLon*.5 + gridPoint.x()*theDeltaLon);
+ modelPoint.setY(-theDeltaLat*.5 + gridPoint.y()*theDeltaLat);
+ modelPoint.setZ(gridPoint.z());
+ }
+ virtual void modelToGlobalGrid(const ModelPoint& modelPoint, GridPoint& gridPoint)const
+ {
+ gridPoint.setX((modelPoint.x()+(theDeltaLon*.5))/theDeltaLon);
+ gridPoint.setY((modelPoint.y()+(theDeltaLat*.5))/theDeltaLat);
+ gridPoint.setZ(modelPoint.z());
+ }
+ virtual void widthHeightInModelSpace(const ossimPlanetTerrainTileId& /* tileId */,
+ osg::Vec2d& deltaXY)const
+ {
+ deltaXY[1] = theDeltaLat;
+ deltaXY[0] = theDeltaLon;
+ }
+ virtual ossim_uint32 numberOfFaces()const
+ {
+ return 1;
+ }
+ virtual bool findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints=3)const
+ {
+ return false;
+ }
+ virtual bool isPolar(const ossimPlanetTerrainTileId& /* id */)const
+ {
+ return false;
+ }
+ /**
+ *
+ */
+ virtual ossimPlanetGridUtility* newBackwardCompatableGrid(ossim_uint32 /* width */,
+ ossim_uint32 /* height */)const
+ {
+ return 0;
+ }
+
+ double theDeltaLat;
+ double theDeltaLon;
+ };
+ ossimPlanetCloudLayer();
+ virtual ~ossimPlanetCloudLayer()
+ {
+ theGeometryArray.clear();
+ }
+ void updateTexture(osg::Image* cloudTexture);
+ void updateTexture(ossim_int64 seed = 0,
+ ossim_int32 coverage = 20,
+ ossim_float64 sharpness = .95);
+
+ virtual void computeMesh(double patchAltitude,
+ ossim_uint32 patchWidth=9,
+ ossim_uint32 patchHeight=9,
+ ossim_uint32 level=3);
+
+ /**
+ * This method allows for changing the opacity of the entire cloud layer
+ */
+ void setAlphaValue(float alpha);
+
+ virtual void traverse(osg::NodeVisitor& nv);
+ void setHeading(ossim_float64 heading)
+ {
+ theHeading = heading;
+ }
+ /**
+ * The speed is in units per hour.
+ */
+ void setSpeedPerHour(ossim_float64 speed, ossimUnitType unit=OSSIM_METERS)
+ {
+ // get it into units per second.
+ //
+ theSpeed = ossimUnitConversionTool(speed, unit).getMeters()/3600.0;
+ }
+ void setSpeedPerSecond(ossim_float64 speed, ossimUnitType unit=OSSIM_METERS)
+ {
+ // get it into units per second.
+ //
+ theSpeed = ossimUnitConversionTool(speed, unit).getMeters();
+ }
+ void setScale(ossim_float64 scale)
+ {
+ theTextureScale[0] = scale;
+ theTextureScale[1] = scale;
+ theTextureScale[2] = 1.0;
+ updateMetersPerPixelCoverage();
+ }
+ void setGrid(ossimPlanetGrid* g)
+ {
+ theGrid = g;
+ }
+ void setAutoUpdateTextureMatrixFlag(bool flag)
+ {
+ theAutoUpdateTextureMatrixFlag = flag;
+ }
+ bool autoUpdateTextureMatrixFlag()const
+ {
+ return theAutoUpdateTextureMatrixFlag;
+ }
+ void moveToLocationLatLonAltitude(const osg::Vec3d& llh);
+
+ ossimPlanetGrid* grid()
+ {
+ return theGrid.get();
+ }
+ void setTextureMatrix(osg::TexMat* texMatrix);
+ osg::TexMat* textureMatrixAttribute()
+ {
+ return theTextureMatrixAttribute.get();
+ }
+ osg::Matrixd& textureMatrix()
+ {
+ return theTextureMatrix;
+ }
+ /**
+ *
+ */
+ void setMaxAltitudeToShowClouds(ossim_float64 maxAltitude);
+ ossim_float64 maxAltitudeToShowClouds()const;
+
+private:
+ void init();
+ void splitTiles(ossimPlanetGrid::TileIds& tiles, ossim_uint32 levels)const;
+ void updateTextureMatrix(double timeScale=0.0);
+ void updateMetersPerPixelCoverage();
+
+ osg::ref_ptr<ossimPlanetGrid> theGrid;
+ osg::ref_ptr<osg::Geode> theGeode;
+ osg::ref_ptr<osg::Image> theImage;
+ osg::ref_ptr<osg::Texture2D> theTexture;
+
+ ossim_float64 theHeading;
+ ossim_float64 theSpeed;
+ osg::Vec3d theTextureTranslation;
+ osg::Vec3d theTextureScale;
+ osg::Matrixd theTextureMatrix;
+ osg::ref_ptr<osg::TexMat> theTextureMatrixAttribute;
+ bool theAutoUpdateTextureMatrixFlag;
+ ossim_uint32 theTextureWidth;
+ ossim_uint32 theTextureHeight;
+ ossim_int32 theMeshLevel;
+
+ ossim_float64 theApproximateMetersPerPixelCoverage;
+ ossim_float64 theMaxAltitudeToShowClouds;
+ osg::Vec3d theCenterLlh;
+
+ geometryPtrArray theGeometryArray;
+};
+
+/**
+ * This perlin noise code was used from the GameDev site written by Huang
+ */
+class OSSIMPLANET_DLL ossimPlanetCloud : public osg::Referenced
+{
+public:
+ enum TextureSize
+ {
+ TEXTURE_SIZE_256_256 = 0,
+ TEXTURE_SIZE_512_512 = 1,
+ TEXTURE_SIZE_1024_1024 = 2,
+ TEXTURE_SIZE_2048_2048 = 3
+ };
+ ossimPlanetCloud(TextureSize=TEXTURE_SIZE_1024_1024);
+ void makeCloud(ossim_int64 seed,
+ ossim_int32 coverage=20,
+ ossim_float64 sharpness=.95);//,
+ //TextureSize size=TEXTURE_SIZE_2048_2048);
+ osg::Image* image();
+
+protected:
+ void makeNoise(ossim_int64 seed);
+ ossim_float64 interpolate(ossim_float64 x, ossim_float64 y, ossim_float64 *map);
+ double noise(ossim_int32 x, ossim_int32 y, ossim_int32 random)const;
+ void overlapOctaves();
+ void expFilter();
+ ossim_int32 theNoiseDataWidth;
+ ossim_int32 theNoiseDataHeight;
+ ossim_int32 theCloudDataWidth;
+ ossim_int32 theCloudDataHeight;
+ std::vector<ossim_float64> theNoise;
+ std::vector<ossim_float64> theCloudData;
+ osg::ref_ptr<osg::Image> theImage;
+
+ ossim_int32 theCoverage;
+ ossim_float64 theSharpness;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetCompass.h b/ossimPlanet/include/ossimPlanet/ossimPlanetCompass.h
new file mode 100644
index 0000000..324df01
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetCompass.h
@@ -0,0 +1,103 @@
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2007, Arizona State University
+// All rights reserved.
+// BSD License: http://www.opensource.org/licenses/bsd-license.html
+// Created by: Jeff Conner
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ossimPlanetCompass_HEADER
+#define ossimPlanetCompass_HEADER
+
+#include <osg/Group>
+#include <string>
+#include "ossimPlanet/ossimPlanetExport.h"
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossim/base/ossimString.h>
+
+
+namespace osg { class MatrixTransform; class Geode; }
+
+
+class OSSIMPLANET_EXPORT ossimPlanetCompass : public osg::Node
+{
+public:
+ ossimPlanetCompass( );
+
+
+ void setCompassTexture ( const ossimFilename& fn );
+// void setInterior ( const ossimFilename& fn );
+// void setCompassTexture(const ossimFilename& ring,
+// const ossimFilename& interior);
+/* osg::Node* compassNode ( ); */
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ bool isAnimating ( );
+ void setAnimation(bool state);
+
+ float heading ( );
+ void setHeading ( float r );
+ void setHeadingRelativeToNorth(const osg::Vec2& north, const osg::Vec2& pos);
+
+ float pitch ( );
+ void setPitch ( float p );
+
+
+ float roll ( );
+ void setRoll(float r);
+
+ void setRotateByViewMatrix ( bool m );
+
+ const osg::Vec3& position ( );
+ void setPosition ( const osg::Vec3& p );
+ void setPositionByPercentage ( float width, float height );
+
+ float scale ( );
+ void setScale ( float s );
+
+ bool isVisible ( );
+
+ void buildCompass ( );
+
+
+ void updateCompass ( );
+
+protected:
+
+ virtual ~ossimPlanetCompass ( );
+
+ osg::Node* buildCompassObject ( const ossimFilename& location);
+ osg::Group* initCompass ( );
+
+ void _showCompass ( );
+ void _hideCompass ( );
+ void _emptyCompass ( );
+ osg::Geode* buildTriangleFan ( const ossimFilename& tex,
+ float zoff,
+ unsigned int render_level,
+ const osg::Vec3& n );
+
+private:
+
+ osg::Vec3 _pos;
+ float _scale;
+ ossimFilename theCompassFilename;
+// ossimFilename theRing;
+// ossimFilename theInterior;
+ unsigned int _numslices;
+ float _radius;
+ osg::ref_ptr<osg::Group> theCompassGroup;
+ osg::ref_ptr<osg::Node> theCompassObject;
+// osg::ref_ptr<osg::Node> theCompassInteriorObject;
+
+ bool _showOrHideCompass, _animating;
+ bool _rotateByView;
+ float _animationStart, _animationEnd, _animationStep;
+
+ float _heading, _pitch, _roll;
+ osg::ref_ptr< osg::Vec4Array > theCommonColorArray;
+ };
+
+#endif // ossimPlanetCompass_HEADER
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetConstants.h b/ossimPlanet/include/ossimPlanet/ossimPlanetConstants.h
new file mode 100644
index 0000000..a6b9365
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetConstants.h
@@ -0,0 +1,111 @@
+#ifndef ossimPlanetConstants_HEADER
+#define ossimPlanetConstants_HEADER
+
+const double OSSIMPLANET_WGS_84_RADIUS_EQUATOR = 6378137.0;
+const double OSSIMPLANET_WGS_84_RADIUS_POLAR = 6356752.3142;
+
+enum ossimPlanetTimeUnit
+{
+ ossimPlanetTimeUnit_SECONDS = 0,
+ ossimPlanetTimeUnit_MINUTES,
+ ossimPlanetTimeUnit_HOURS,
+};
+
+enum ossimPlanetLandRefreshType
+{
+ ossimPlanetLandRefreshType_NONE = 0,
+ ossimPlanetLandRefreshType_TEXTURE = 1,
+ ossimPlanetLandRefreshType_GEOM = 2,
+ ossimPlanetLandRefreshType_PRUNE = 4,
+};
+
+enum ossimPlanetLandType
+{
+ ossimPlanetLandType_NONE = 0,
+ ossimPlanetLandType_FLAT = 1,
+ ossimPlanetLandType_NORMALIZED_ELLIPSOID = 2,
+ ossimPlanetLandType_ELLIPSOID = 3,
+ ossimPlanetLandType_ORTHOFLAT = 4
+};
+
+enum ossimPlanetPriorityType
+{
+ ossimPlanetLandPriorityType_NONE = 0,
+ ossimPlanetLandPriorityType_LINE_OF_SITE_INTERSECTION = 1,
+ ossimPlanetLandPriorityType_EYE_POSITION = 2
+};
+
+enum ossimPlanetAltitudeMode
+{
+ ossimPlanetAltitudeMode_NONE = 0,
+ ossimPlanetAltitudeMode_CLAMP_TO_GROUND = 1,
+ ossimPlanetAltitudeMode_RELATIVE_TO_GROUND = 2,
+ ossimPlanetAltitudeMode_ABSOLUTE = 3
+};
+
+enum ossimPlanetKmlUnits
+{
+ ossimPlanetKmlUnits_NONE = 0,
+ ossimPlanetKmlUnits_FRACTION = 1,
+ ossimPlanetKmlUnits_PIXELS = 2,
+ ossimPlanetKmlUnits_INSET_PIXELS = 3
+};
+
+enum ossimPlanetKmlStyleState
+{
+ ossimPlanetKmlStyleState_NONE = 0,
+ ossimPlanetKmlStyleState_NORMAL = 1,
+ ossimPlanetKmlStyleState_HIGHLIGHT = 2,
+};
+
+enum ossimPlanetKmlRefreshMode
+{
+ ossimPlanetKmlRefreshMode_NONE = 0,
+ ossimPlanetKmlRefreshMode_ON_CHANGE = 1,
+ ossimPlanetKmlRefreshMode_ON_INTERVAL = 2,
+ ossimPlanetKmlRefreshMode_ON_EXPIRE = 3
+};
+
+enum ossimPlanetKmlViewRefreshMode
+{
+ ossimPlanetKmlViewRefreshMode_NONE = 0,
+ ossimPlanetKmlViewRefreshMode_NEVER = 1,
+ ossimPlanetKmlViewRefreshMode_ON_REQUEST = 2,
+ ossimPlanetKmlViewRefreshMode_ON_STOP = 3,
+ ossimPlanetKmlViewRefreshMode_ON_REGION = 4
+};
+
+enum ossimPlanetKmlColorMode
+{
+ ossimPlanetKmlColorMode_NONE = 0,
+ ossimPlanetKmlColorMode_NORMAL = 1,
+ ossimPlanetKmlColorMode_RANDOM = 2
+};
+
+enum ossimPlanetTextureLayerStateCode // bit vector
+{
+ ossimPlanetTextureLayer_VALID = 0,
+ ossimPlanetTextureLayer_NO_SOURCE_DATA = 1,
+ ossimPlanetTextureLayer_NO_GEOM = 2,
+ ossimPlanetTextureLayer_NO_OVERVIEWS = 4,
+ ossimPlanetTextureLayer_NO_HISTOGRAMS = 8,
+ ossimPlanetTextureLayer_NOT_OPENED = 16,
+ ossimPlanetTextureLayer_ALL = (ossimPlanetTextureLayer_NO_SOURCE_DATA|
+ ossimPlanetTextureLayer_NO_GEOM|
+ ossimPlanetTextureLayer_NO_OVERVIEWS|
+ ossimPlanetTextureLayer_NO_HISTOGRAMS|
+ ossimPlanetTextureLayer_NOT_OPENED)
+};
+
+enum ossimPlanetIoDirection
+{
+ ossimPlanetIoDirection_NONE = 0,
+ ossimPlanetIoDirection_IN = 1,
+ ossimPlanetIoDirection_OUT = 2,
+ ossimPlanetIoDirection_INOUT= 3
+};
+
+#include <cmath>
+
+#define OSSIMPLANET_NULL_HEIGHT ((ossim_float32)1.0/FLT_EPSILON)
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetCubeGrid.h b/ossimPlanet/include/ossimPlanet/ossimPlanetCubeGrid.h
new file mode 100644
index 0000000..2e74bce
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetCubeGrid.h
@@ -0,0 +1,37 @@
+#ifndef ossimPlanetCubeGrid_HEADER
+#define ossimPlanetCubeGrid_HEADER
+#include <ossimPlanet/ossimPlanetGridUtility.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetCubeGrid : public ossimPlanetGridUtility
+{
+public:
+ ossimPlanetCubeGrid(ossim_uint32 tileWidth = 256,
+ ossim_uint32 tileHeight = 256)
+ :ossimPlanetGridUtility(tileWidth, tileHeight)
+ {
+ }
+ virtual void getPixelScale(double& dx,
+ double& dy,
+ ossimUnitType& pixelScaleUnits,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual void getWidthHeightInDegrees(double& deltaX,
+ double& deltaY,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ // this is from GeoFusion SPEC
+ virtual void getLatLon(osg::Vec3d& latLon,
+ const ossimPlanetGridUtility::GridPoint& gridPoint)const;
+
+ // this is from Geofusion SPEC
+ virtual void getGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ const osg::Vec3d& latLon)const;
+
+ virtual ossim_uint32 getNumberOfFaces()const;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetDatabasePager.h b/ossimPlanet/include/ossimPlanet/ossimPlanetDatabasePager.h
new file mode 100644
index 0000000..e7679d6
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetDatabasePager.h
@@ -0,0 +1,67 @@
+#ifndef ossimPlanetDatabasePager_HEADER
+#define ossimPlanetDatabasePager_HEADER
+#include <osgDB/DatabasePager>
+#include <ossimPlanet/ossimPlanetExport.h>
+//#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+class OSSIMPLANET_DLL ossimPlanetDatabasePager : public osgDB::DatabasePager
+{
+public:
+ ossimPlanetDatabasePager();
+ virtual DatabasePager* clone() const { return new ossimPlanetDatabasePager(*this); }
+ #if 0
+ virtual bool isRunning() const;
+
+ virtual void signalBeginFrame(const osg::FrameStamp* framestamp);
+ virtual void signalEndFrame();
+ virtual void updateSceneGraph(const osg::FrameStamp& frameStamp);
+ virtual void compileGLObjects(osg::State& state,double& availableTime);
+ virtual void compileAllGLObjects(osg::State& state);
+
+ #endif
+#if 0
+ class Callback : public osg::Referenced
+ {
+ public:
+ Callback(){}
+ virtual void updateSceneGraph(){}
+ virtual void noMoreWork(){}
+ virtual void doingWork(){}
+ };
+ typedef std::vector<osg::ref_ptr<ossimPlanetDatabasePager::Callback> > CallbackListType;
+ ossimPlanetDatabasePager();
+ virtual DatabasePager* clone() const { return new ossimPlanetDatabasePager(*this); }
+ virtual ~ossimPlanetDatabasePager();
+ virtual void run();
+ virtual int cancel();
+ virtual void invalidateRequest(const std::string& requestString);
+ virtual void requestNodeFile(const std::string& fileName,osg::Group* group, float priority, const osg::FrameStamp* framestamp);
+ bool listsAreEmpty()const;
+
+ void addCallback(osg::ref_ptr<ossimPlanetDatabasePager::Callback> callback);
+ void removeCallback(osg::ref_ptr<ossimPlanetDatabasePager::Callback> callback);
+ void removeRequest(osg::Group* group);
+ void addToDeleteList(osg::Object* obj);
+ void clearRequests();
+ virtual void updateSceneGraph(double currentFrameTime);
+
+ class MyFindCompileableGLObjectsVisitor;
+ struct MySortFileRequestFunctor;
+ struct MyCompileOperation;
+ friend struct MyCompileOperation;
+ friend struct MySortFileRequestFunctor;
+ friend class MyFindCompileableGLObjectsVisitor;
+#endif
+
+protected:
+#if 0
+ void notifyDoingWork();
+ void notifyNoMoreWork();
+ void notifyUpdateSceneGraph();
+ ossimPlanetReentrantMutex theCallbackListMutex;
+ ossimPlanetDatabasePager::CallbackListType theCallbackList;
+// SceneNotificationCallbackListType theCallbackList;
+#endif
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetDepthPartitionNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetDepthPartitionNode.h
new file mode 100644
index 0000000..c343805
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetDepthPartitionNode.h
@@ -0,0 +1,104 @@
+/* -*-c++-*-
+*
+* OpenSceneGraph example, osgdepthpartion.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#ifndef _OF_DEPTHPARTITIONNODE_
+#define _OF_DEPTHPARTITIONNODE_
+#include <ossimPlanet/ossimPlanetExport.h>
+#include "ossimPlanetDistanceAccumulator.h"
+#include <osg/Group>
+#include <osg/Camera>
+
+/**********************************************************
+ * Ravi Mathur
+ * OpenFrames API, class DepthPartitionNode
+ * A type of osg::Group that analyzes a scene, then partitions it into
+ * several segments that can be rendered separately. Each segment
+ * is small enough in the z-direction to avoid depth buffer problems
+ * for very large scenes.
+**********************************************************/
+class OSSIMPLANET_DLL ossimPlanetDepthPartitionNode : public osg::Group
+{
+ public:
+ ossimPlanetDepthPartitionNode();
+ ossimPlanetDepthPartitionNode(const ossimPlanetDepthPartitionNode& dpn,
+ const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
+
+ META_Node( OpenFrames, ossimPlanetDepthPartitionNode ); // Common Node functions
+
+ /** Set the active state. If not active, this node will simply add the
+ specified scene as it's child, without analyzing it at all. */
+ void setActive(bool active);
+ inline bool getActive() const { return _active; }
+
+ /** Specify whether the color buffer should be cleared before the first
+ Camera draws it's scene. */
+ void setClearColorBuffer(bool clear);
+ inline bool getClearColorBuffer() const { return _clearColorBuffer; }
+
+ /** Specify the render order for each Camera */
+ void setRenderOrder(osg::Camera::RenderOrder order);
+ inline osg::Camera::RenderOrder getRenderOrder() const
+ { return _renderOrder; }
+
+ /** Set/get the maximum depth that the scene will be traversed to.
+ Defaults to UINT_MAX. */
+ void setMaxTraversalDepth(unsigned int depth)
+ { _distAccumulator->setMaxDepth(depth); }
+
+ inline unsigned int getMaxTraversalDepth() const
+ { return _distAccumulator->getMaxDepth(); }
+
+ /** Override update and cull traversals */
+ virtual void traverse(osg::NodeVisitor &nv);
+
+ /** Catch child management functions so the Cameras can be informed
+ of added or removed children. */
+ virtual bool addChild(osg::Node *child);
+ virtual bool insertChild(unsigned int index, osg::Node *child);
+ virtual bool removeChildren(unsigned int pos, unsigned int numRemove = 1);
+ virtual bool setChild(unsigned int i, osg::Node *node);
+
+ protected:
+ typedef std::vector< osg::ref_ptr<osg::Camera> > CameraList;
+
+ virtual ~ossimPlanetDepthPartitionNode();
+
+ void init();
+
+ // Creates a new Camera object with default settings
+ osg::Camera* createOrReuseCamera(const osg::Matrix& proj,
+ double znear, double zfar,
+ const unsigned int &camNum);
+
+ bool _active; // Whether partitioning is active on the scene
+
+ // The NodeVisitor that computes cameras for the scene
+ osg::ref_ptr<ossimPlanetDistanceAccumulator> _distAccumulator;
+
+ osg::Camera::RenderOrder _renderOrder;
+ bool _clearColorBuffer;
+
+ // Cameras that should be used to draw the scene. These cameras
+ // will be reused on every frame in order to save time and memory.
+ CameraList _cameraList;
+ unsigned int _numCameras; // Number of Cameras actually being used
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetDestinationCommandAction.h b/ossimPlanet/include/ossimPlanet/ossimPlanetDestinationCommandAction.h
new file mode 100644
index 0000000..f42d44b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetDestinationCommandAction.h
@@ -0,0 +1,85 @@
+#ifndef ossimPlanetDestinationCommandAction_HEADER
+#define ossimPlanetDestinationCommandAction_HEADER
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossim/base/ossimString.h>
+
+class OSSIMPLANET_DLL ossimPlanetDestinationCommandAction : public ossimPlanetAction
+{
+public:
+ ossimPlanetDestinationCommandAction(const ossimString& sourcecode = ossimString(),
+ const ossimString& originatingFederate = defaultOrigin());
+ ossimPlanetDestinationCommandAction(const ossimPlanetDestinationCommandAction& src)
+ :ossimPlanetAction(src),
+ theTokens(src.theTokens),
+ theArgCount(src.theArgCount)
+ {
+ }
+ virtual ossimPlanetDestinationCommandAction* toDestinationCommandAction()
+ {
+ return this;
+ }
+ virtual const ossimPlanetDestinationCommandAction* toDestinationCommandAction()const
+ {
+ return this;
+ }
+ virtual ossimPlanetAction* clone()const
+ {
+ return new ossimPlanetDestinationCommandAction(*this);
+ }
+ virtual ossimPlanetAction* cloneType()const
+ {
+ return new ossimPlanetDestinationCommandAction();
+ }
+ ossimString argListSourceCode() const;
+ virtual bool setSourceCode(const ossimString& code);
+
+ virtual void setTarget(const ossimString& targetPath)
+ {
+ ossimPlanetAction::setTarget(targetPath);
+ if(theTokens.size())
+ {
+ theTokens[0] = targetPath.string();
+ }
+ }
+
+ virtual void setCommand(const ossimString& value)
+ {
+ ossimPlanetAction::setCommand(value);
+ if(theTokens.size()>1)
+ {
+ theTokens[1] = value.string();
+ }
+ }
+ unsigned int argCount() const
+ {
+ return theArgCount;
+ }
+
+ const std::string& arg(unsigned int i) const
+ {
+ assert(i >= 1 && i <= argCount());
+ return theTokens[i+1];
+ }
+ void setTargetCommandArg(const ossimString& target,
+ const ossimString& command,
+ const ossimString& arg)
+ {
+ theArgCount = 1;
+ theTokens.resize(3);
+ theTokens[0] = target.string();
+ theTokens[1] = command.string();
+ theTokens[2] = arg.string();
+ }
+ ossimString argListSource() const;
+ // source code of the argument list
+ virtual void print(std::ostream& out)const;
+ virtual void read(std::istream& in);
+
+protected:
+ std::vector<std::string> theTokens;
+ unsigned int theArgCount;
+
+ static const char theWhitespace[];
+ // characters considered to be whitespace
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetDistanceAccumulator.h b/ossimPlanet/include/ossimPlanet/ossimPlanetDistanceAccumulator.h
new file mode 100644
index 0000000..dfa8db3
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetDistanceAccumulator.h
@@ -0,0 +1,116 @@
+/* -*-c++-*-
+*
+* OpenSceneGraph example, osgdepthpartion.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#ifndef _OF_DISTANCEACCUMULATOR_
+#define _OF_DISTANCEACCUMULATOR_
+
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Group>
+#include <osg/NodeVisitor>
+#include <osg/Polytope>
+#include <osg/fast_back_stack>
+
+#define CURRENT_CLASS ossimPlanetDistanceAccumulator
+/**********************************************************
+ * Ravi Mathur
+ * OpenFrames API, class DistanceAccumulator
+ * Class that traverses the scene and computes the distance to each
+ * visible drawable, and splits up the scene if the drawables are
+ * too far away (in the z direction) from each other.
+**********************************************************/
+class OSSIMPLANET_DLL CURRENT_CLASS : public osg::NodeVisitor
+{
+ public:
+ typedef std::pair<double, double> DistancePair;
+ typedef std::vector<DistancePair> PairList;
+
+ CURRENT_CLASS();
+
+ virtual void apply(osg::Node &node);
+ virtual void apply(osg::Projection &proj);
+ virtual void apply(osg::Transform &transform);
+ virtual void apply(osg::Geode &geode);
+
+ // Specify the modelview & projection matrices
+ void setMatrices(const osg::Matrix &modelview,
+ const osg::Matrix &projection);
+
+ // Reset visitor before a new traversal
+ virtual void reset();
+
+ // Create a (near,far) distance pair for each camera of the specified
+ // distance pair list and distance limits.
+ void computeCameraPairs();
+
+ // Get info on the cameras that should be used for scene rendering
+ PairList& getCameraPairs() { return _cameraPairs; }
+
+ // Get info on the computed distance pairs
+ PairList& getDistancePairs() { return _distancePairs; }
+
+ // Get info on the computed nearest/farthest distances
+ DistancePair& getLimits() { return _limits; }
+
+ // Set/get the desired near/far ratio
+ void setNearFarRatio(double ratio);
+ inline double getNearFarRatio() const { return _nearFarRatio; }
+
+ inline void setMaxDepth(unsigned int depth) { _maxDepth = depth; }
+ inline unsigned int getMaxDepth() const { return _maxDepth; }
+
+ protected:
+ virtual ~CURRENT_CLASS();
+
+ void pushLocalFrustum();
+ void pushDistancePair(double zNear, double zFar);
+ bool shouldContinueTraversal(osg::Node &node);
+
+ // Stack of matrices accumulated during traversal
+ osg::fast_back_stack<osg::Matrix> _viewMatrices;
+ osg::fast_back_stack<osg::Matrix> _projectionMatrices;
+
+ // Main modelview/projection matrices
+ osg::Matrix _modelview, _projection;
+
+ // The view frusta in local coordinate space
+ osg::fast_back_stack<osg::Polytope> _localFrusta;
+
+ // Bounding box corners that should be used for cull computation
+ typedef std::pair<unsigned int, unsigned int> bbCornerPair;
+ osg::fast_back_stack<bbCornerPair> _bbCorners;
+
+ // Nar/far planes that should be used for each camera
+ PairList _cameraPairs;
+
+ // Accumulated pairs of min/max distances
+ PairList _distancePairs;
+
+ // The closest & farthest distances found while traversing
+ DistancePair _limits;
+
+ // Ratio of nearest/farthest clip plane for each section of the scene
+ double _nearFarRatio;
+
+ // Maximum depth to traverse to
+ unsigned int _maxDepth, _currentDepth;
+};
+#undef CURRENT_CLASS
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetDtedElevationDatabase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetDtedElevationDatabase.h
new file mode 100644
index 0000000..9730976
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetDtedElevationDatabase.h
@@ -0,0 +1,85 @@
+#ifndef ossimPlanetDtedElevationDatabase_HEADER
+#define ossimPlanetDtedElevationDatabase_HEADER
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <ossim/elevation/ossimDtedHandler.h>
+#include <osg/Timer>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <OpenThreads/ReentrantMutex>
+
+class OSSIMPLANET_DLL ossimPlanetDtedElevationDatabase : public ossimPlanetElevationDatabase
+{
+public:
+ ossimPlanetDtedElevationDatabase();
+ ossimPlanetDtedElevationDatabase(const ossimPlanetDtedElevationDatabase& src);
+ virtual ~ossimPlanetDtedElevationDatabase();
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ virtual void resetStats()const;
+
+ virtual ossimPlanetTextureLayerStateCode open(const std::string& location);
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+protected:
+ class DtedInfo : public osg::Referenced
+ {
+ public:
+ double theMinLat, theMinLon, theMaxLat, theMaxLon;
+ double theNumLatPoints;
+ double theNumLonLines;
+ double theLatSpacing;
+ double theLonSpacing;
+ ossimFilename theFilename;
+ ossimRefPtr<ossimDtedHandler> theHandler;
+ osg::Timer_t theTimeStamp;
+ };
+
+ typedef std::map<std::string, osg::ref_ptr<DtedInfo> > DtedFilePointerList;
+
+
+ osg::ref_ptr<ossimPlanetDtedElevationDatabase::DtedInfo> getInfo(const std::string& name);
+ void shrinkFilePointers();
+ ossimFilename buildFilename(double lat, double lon)const;
+ osg::ref_ptr<ossimPlanetDtedElevationDatabase::DtedInfo> findDtedInfo(const std::string& name);
+ double getHeightAboveMSL(osg::ref_ptr<DtedInfo> info, double lat, double lon)const;
+ ossim_sint16 convertSignedMagnitude(ossim_uint16& s) const;
+
+ std::string theLocation;
+ mutable bool theOpenFlag;
+ ossim_uint32 theMaxOpenFiles;
+ ossim_uint32 theMinOpenFiles;
+ DtedFilePointerList theFilePointers;
+ ossim_float32 theNullHeightValue;
+ bool theSwapBytesFlag;
+ mutable OpenThreads::ReentrantMutex theDtedInfoMutex;
+
+};
+inline ossim_sint16 ossimPlanetDtedElevationDatabase::convertSignedMagnitude(ossim_uint16& s) const
+{
+ // DATA_VALUE_MASK 0x7fff = 0111 1111 1111 1111
+ // DATA_SIGN_MASK 0x8000 = 1000 0000 0000 0000
+
+ // First check to see if the bytes need swapped.
+ s = (theSwapBytesFlag ? ( ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8) ) : s);
+
+ // If the sign bit is set, mask it out then multiply by negative one.
+ if (s & 0x8000)
+ {
+ return (static_cast<ossim_sint16>(s & 0x7fff) * -1);
+ }
+
+ return static_cast<ossim_sint16>(s);
+}
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetElevationDatabase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationDatabase.h
new file mode 100644
index 0000000..2b98882
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationDatabase.h
@@ -0,0 +1,69 @@
+#ifndef ossimPlanetElevationDatabase_HEADER
+#define ossimPlanetElevationDatabase_HEADER
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetGridUtility.h>
+#include <ossimPlanet/ossimPlanetExtents.h>
+#include <string>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+
+class OSSIMPLANET_DLL ossimPlanetElevationDatabase : public ossimPlanetTextureLayer
+{
+public:
+ ossimPlanetElevationDatabase()
+ :ossimPlanetTextureLayer(),
+ theFillNullWithGeoidOffsetFlag(false)
+ {}
+ ossimPlanetElevationDatabase(const ossimPlanetElevationDatabase& src)
+ : ossimPlanetTextureLayer(src)
+ {
+ }
+
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(const ossimPlanetTerrainTileId& tileId,
+ osg::ref_ptr<ossimPlanetGrid> theGrid);
+
+ virtual ossimPlanetTextureLayerStateCode open(const std::string& location)=0;
+
+ virtual const std::string& getLocation()const
+ {
+ return theLocation;
+ }
+ bool fillNullWithGeoidOffsetFlag()const
+ {
+ return theFillNullWithGeoidOffsetFlag;
+ }
+ virtual void setFillNullWithGeoidOffsetFlag(bool flag)
+ {
+ theFillNullWithGeoidOffsetFlag = flag;
+ }
+ virtual void setGeoRefModel(osg::ref_ptr<ossimPlanetGeoRefModel> model)
+ {
+ theGeoRefModel = model.get();
+ }
+ ossimPlanetGeoRefModel* geoRefModel()const
+ {
+ return theGeoRefModel.get();
+ }
+ virtual void sortByGsd()
+ {
+
+ }
+protected:
+ /**
+ *
+ * destData is always assumed to be 1 band float and both buffers are of the same size. It will make sure it's float before
+ * merging the src into the destination. This function basically copys good pixels into
+ * non null regions of the destination.
+ *
+ */
+ void mergeDataObjects(ossimRefPtr<ossimImageData> destData,
+ ossimRefPtr<ossimImageData> srcData);
+
+ std::string theLocation;
+ bool theFillNullWithGeoidOffsetFlag;
+ osg::ref_ptr<ossimPlanetGeoRefModel> theGeoRefModel;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetElevationDatabaseGroup.h b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationDatabaseGroup.h
new file mode 100644
index 0000000..0d3b111
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationDatabaseGroup.h
@@ -0,0 +1,58 @@
+#ifndef ossimPlanetElevationDatabaseGroup_HEADER
+#define ossimPlanetElevationDatabaseGroup_HEADER
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetElevationDatabaseGroup : public ossimPlanetTextureLayerGroup
+{
+public:
+ ossimPlanetElevationDatabaseGroup();
+
+ ossimPlanetElevationDatabaseGroup(const ossimPlanetElevationDatabaseGroup& src);
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+
+ virtual bool replaceLayer(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer);
+
+ virtual bool addTop(osg::ref_ptr<ossimPlanetTextureLayer> layer);
+ virtual bool addBeforeIdx(ossim_uint32 idx, osg::ref_ptr<ossimPlanetTextureLayer> layer);
+ virtual bool addBeforeLayer(const osg::ref_ptr<ossimPlanetTextureLayer> beforeLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd);
+ virtual bool addAfterIdx(ossim_int32 idx, osg::ref_ptr<ossimPlanetTextureLayer> layer);
+ virtual bool addAfterLayer(const osg::ref_ptr<ossimPlanetTextureLayer> afterLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd);
+ virtual bool addBottom(osg::ref_ptr<ossimPlanetTextureLayer> layer);
+
+ virtual void setGeoRefModel(osg::ref_ptr<ossimPlanetGeoRefModel> model);
+ virtual void setFillNullWithGeoidOffsetFlag(bool flag);
+ bool fillNullWithGeoidOffsetFlag()const
+ {
+ return theFillNullWithGeoidOffsetFlag;
+ }
+
+protected:
+ /**
+ *
+ * Merging elevation cells are done differently. We will override the base classes mergeImage.
+ *
+ */
+ virtual void mergeImage(ossimPlanetImage* result,
+ const ossimPlanetImage* source)const;
+ void setPixelStatus(ossimPlanetImage* image);
+
+ osg::ref_ptr<ossimPlanetGeoRefModel> theGeoRefModel;
+ bool theFillNullWithGeoidOffsetFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetElevationFactory.h b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationFactory.h
new file mode 100644
index 0000000..5f7530f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationFactory.h
@@ -0,0 +1,12 @@
+#ifndef ossimPlanetElevationFactory_HEADER
+#define ossimPlanetElevationFactory_HEADER
+#include <ossimPlanet/ossimPlanetElevationRegistry.h>
+class ossimPlanetElevationFactory : public ossimPlanetElevationRegistry::FactoryBase
+{
+public:
+ ossimPlanetElevationFactory();
+ virtual ossimPlanetElevationDatabase* openDatabase(const ossimString& location);
+ static ossimPlanetElevationFactory* instance();
+};
+
+#endif
\ No newline at end of file
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetElevationGrid.h b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationGrid.h
new file mode 100644
index 0000000..3fac884
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationGrid.h
@@ -0,0 +1,60 @@
+#ifndef ossimPlanetElevationGrid_HEADER
+#define ossimPlanetElevationGrid_HEADER
+#include <vector>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetElevationGrid : public osg::Referenced
+{
+public:
+ ossimPlanetElevationGrid(ossim_uint32 w=1,
+ ossim_uint32 h=1);
+
+ float& operator[](ossim_uint32 idx)
+ {
+ return theGrid[idx];
+ }
+ const float& operator[](ossim_uint32 idx)const
+ {
+ return theGrid[idx];
+ }
+ float* row(ossim_uint32 rowIdx)
+ {
+ return &theGrid[rowIdx*theWidth];
+ }
+ ossim_uint32 getWidth()const
+ {
+ return theWidth;
+ }
+ ossim_uint32 getHeight()const
+ {
+ return theHeight;
+ }
+
+ void resize(ossim_uint32 w,
+ ossim_uint32 h);
+
+ const ossim_float32* data()const
+ {
+ return theGrid;
+ }
+ ossim_float32* data()
+ {
+ return theGrid;
+ }
+ osg::ref_ptr<ossimPlanetElevationGrid> scaleBy2Nearest()const;
+ osg::ref_ptr<ossimPlanetElevationGrid> scaleBy2Bilinear()const;
+ void copyGrid(ossim_uint32 ulx,
+ ossim_uint32 uly,
+ osg::ref_ptr<ossimPlanetElevationGrid> output)const;
+ bool isEqualTo(osg::ref_ptr<ossimPlanetElevationGrid> grid)const;
+protected:
+ virtual ~ossimPlanetElevationGrid();
+ ossim_uint32 theWidth;
+ ossim_uint32 theHeight;
+ ossim_float32* theGrid;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetElevationRegistry.h b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationRegistry.h
new file mode 100644
index 0000000..c31dbf7
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetElevationRegistry.h
@@ -0,0 +1,36 @@
+#ifndef ossimPlanetElevationRegistry_HEADER
+#define ossimPlanetElevationRegistry_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+
+class OSSIMPLANET_DLL ossimPlanetElevationRegistry
+{
+public:
+ class OSSIMPLANET_DLL FactoryBase
+ {
+ public:
+ virtual ~FactoryBase(){}
+ virtual ossimPlanetElevationDatabase* openDatabase(const ossimString& location)=0;
+
+ ossimString id(){return theId;}
+ void setId(const ossimString& value){theId = value;}
+ protected:
+ ossimString theId;
+ };
+ typedef std::vector<FactoryBase*> FactoryList;
+
+ ossimPlanetElevationRegistry();
+ bool registerFactory(FactoryBase* factory);
+ void unregisterFactory(FactoryBase* factory);
+ ossimPlanetElevationDatabase* openDatabase(const ossimString& location);
+
+ static ossimPlanetElevationRegistry* instance();
+
+protected:
+ ossimPlanetReentrantMutex theMutex;
+ FactoryList theFactoryList;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetEphemeris.h b/ossimPlanet/include/ossimPlanet/ossimPlanetEphemeris.h
new file mode 100644
index 0000000..b884bb7
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetEphemeris.h
@@ -0,0 +1,392 @@
+#ifndef ossimPlanetEphemeris_HEADER
+#define ossimPlanetEphemeris_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Material>
+
+class ossimPlanet;
+class ossimPlanetCloudLayer;
+class OSSIMPLANET_DLL ossimPlanetEphemeris : public ossimPlanetLayer
+{
+public:
+ /**
+ * These are setting that will be used for display purposes. The members
+ * can be ored together to formula the current active set of members to use.
+ *
+ * SUN_LIGHT enables sun lighting calculations. It will automatically set the sun directional
+ * vector and positioning relative to the current ossimPlanet geospatial model.
+ * MOON_LIGHT enables moon lighting calculations. It will automatically set the moon directional
+ * vector and positioning relative to the current ossimPlanet geospatial model.
+ */
+ enum Members
+ {
+ NO_MEMBERS = 0,
+ SUN_LIGHT = 1, // Enable the default Sun lighting
+ MOON_LIGHT = 2, // Enable the default moon lighting
+ AMBIENT_LIGHT = 4,
+ SUN = 8,
+ MOON = 16,
+ SKY = 32,
+ FOG = 64,
+ ALL_MEMBERS = SKY|SUN_LIGHT|MOON_LIGHT|SUN|MOON|AMBIENT_LIGHT|FOG
+ };
+
+ enum FogMode
+ {
+ LINEAR = 0, ///<Linear fog
+ EXP, ///<Exponential fog
+ EXP2, ///<Exponential squared fog
+ //ADV ///<Advanced light scattering "fog" RESERVED FOR FUTURE
+ };
+
+ typedef std::map<double, double> IntensityTableType;
+ class LightingCallback : public osg::Referenced
+ {
+ public:
+ virtual void operator()(ossimPlanetEphemeris* /*ephemeris*/,
+ osg::LightSource* /*light*/)
+ {
+ }
+ };
+ ossimPlanetEphemeris(ossim_uint64 membersBitMap=NO_MEMBERS);
+ virtual ~ossimPlanetEphemeris();
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ osg::Vec3d eyePositionXyz()const;
+ osg::Vec3d eyePositionLatLonHeight()const;
+ /**
+ * @brief Allows you to set what the current active members are. See the
+ * enumeration Members for more detail. This is an "ored" bit vector
+ * of Members to use.
+ */
+ void setMembers(ossim_uint64 membersBitMap);
+
+ /**
+ * @return The members bitmap describing the current members active in the
+ * ephemeris model. See the enumeration Members for more details
+ */
+ ossim_uint64 members()const;
+
+ /**
+ * @param statest The root graph to use for light source settings.
+ */
+ void setRoot(osg::Group* group);
+
+
+ /**
+ * @brief Sets the index to use for the moonlight source.
+ *
+ * @param idxNumber The openGL Light index to use for the moon lighting
+ */
+ void setMoonLightIndex(ossim_uint32 idxNumber);
+
+ /**
+ * @return the current moonlight index
+ */
+ ossim_uint32 moonLightIndex()const;
+
+ void setMoonLightCallback(LightingCallback* callback);
+
+ void setMoonCullCallback(osg::NodeCallback* callback);
+
+ osg::Vec3d moonPositionXyz()const;
+ osg::Vec3d moonPositionLatLonHeight()const;
+
+ /**
+ * @brief Sets the index to use for the sunlight source.
+ *
+ * @param idxNumber The openGL Light index to use for the sun lighting
+ */
+ void setSunLightIndex(ossim_uint32 idxNumber);
+
+ /**
+ * @return the current moonlight index
+ */
+ ossim_uint32 sunLightIndex()const;
+
+ void setSunLightCallback(LightingCallback* callback);
+
+ /**
+ * @brief Sets the cull call back to use for the sun model
+ *
+ * @param callback The call back function to use
+ */
+ void setSunCullCallback(osg::NodeCallback* callback);
+
+ osg::Vec3d sunPositionXyz()const;
+ osg::Vec3d sunPositionLatLonHeight()const;
+ /**
+ * Allows one to turn off auto update for sun color calculations.
+ */
+ void setAutoUpdateSunColorFlag(bool flag);
+
+ /**
+ * @brief OpenGL light index to use for the ambient lighting.
+ *
+ * @param idxNumber The openGL Light index to use for the sun lighting
+ */
+ void setGlobalAmbientLightIndex(ossim_uint32 idx);
+
+ /**
+ * @brief returns the current ambient index.
+ *
+ * @return the ambient index.
+ */
+ ossim_uint32 globalAmbientLightIndex()const;
+
+ /**
+ * Allows one to change the color value for the global ambient lighting. The
+ * color is a normalized r,g,b value and range from 0..1
+ *
+ * @param ambient The normalized color vector ranging from 0..1 for each RGB component.
+ */
+ void setGlobalAmbientLight(const osg::Vec3d& ambient);
+ /**
+ * This will set the date to use. If this is set then the
+ * auto update of the current time is disabled and will use
+ * this date as a fixed shading. When using this method we basically assume
+ * that you are driving the date and time. To reset back to auto update just call
+ * the setAutoUpdateToCurrentTimeFlag.
+ *
+ * Note, for Ephermis calculations we normalize the date on the fly to GMT time
+ * so we will always hold onto the original date passed.
+ *
+ * @param time an ossimLocalTm object.
+ */
+ void setDate(const ossimLocalTm& date);
+
+ /**
+ * This is to allow you to let the ephemeris updates continually
+ * change based on the current time
+ */
+ void setAutoUpdateToCurrentTimeFlag(bool flag);
+
+ /**
+ * This will disable the Auto update to current time setting and do a relative
+ * displacement of the current date settings to the sim time passed in the osg::NodeVisitor
+ *
+ * Currently the relative simulation time displacement units must be in seconds.
+ */
+ void setApplySimulationTimeOffsetFlag(bool flag);
+
+ /**
+ * This is used by the ossimPlanetViewer to setup a slave camera for the drawing
+ * of the sun moon and dome. We were having problems with large displacements being in
+ * the same graph as the terrain. The near and far planes were causing the terrain to
+ * get clipped at low altitudes.
+ *
+ * This might go away in the future, but for now I am playing with coupling to the viewer's master
+ * camera.
+ */
+ void setCamera(osg::Camera* camera);
+
+ /**
+ * Will use the visibility to set the far plane and the density values of the fog. The visibility is
+ * in meters.
+ *
+ * @param visibility Value specifies visibility in meter distance.
+ */
+ void setVisibility(ossim_float64 visibility);
+
+
+ /**
+ * This returns the internal representation of the visibility.
+ */
+ ossim_float64 visibility()const;
+
+ /**
+ * Allows one to pass a texture in by file. It uses this texture to show the position
+ * of the sun.
+ *
+ * @param texture Filename for the texture. Typically a file format supported by OSG and has
+ * an alpha channel. Best is an RBA in png format.
+ */
+ void setSunTextureFromFile(const ossimFilename& texture);
+
+ /**
+ * Allows one to pass a texture by osg::Image. It uses this texture to show the position
+ * of the sun.
+ *
+ * @param texture Image for the texture. Should be an RGBA type image.
+ */
+ void setSunTextureFromImage(osg::Image* texture);
+
+ /**
+ * @brief Sets the scale to use for the sun model
+ *
+ * @param scale, The scale to use
+ */
+ void setSunScale(const osg::Vec3d& scale);
+
+ /**
+ * Allows one to pass a texture in by file. It uses this texture to show the position
+ * of the moon.
+ *
+ * @param texture Filename for the texture. Typically a file format supported by OSG and has
+ * an alpha channel. Best is an RBA in png format.
+ */
+ void setMoonTextureFromFile(const ossimFilename& texture);
+
+ /**
+ * Allows one to pass a texture by osg::Image. It uses this texture to show the position
+ * of the moon.
+ *
+ * @param texture Image for the texture. Should be an RGBA type image.
+ */
+ void setMoonTextureFromImage(osg::Image* texture);
+
+ void setMoonScale(const osg::Vec3d& scale);
+
+ void setSunMinMaxPixelSize(ossim_uint32 minPixelSize,
+ ossim_uint32 maxPixelSize);
+
+ void setMaximumAltitudeToShowDomeInMeters(ossim_float64 maxAltitude);
+ void setMaximumAltitudeToShowFogInMeters(ossim_float64 maxAltitude);
+
+ /**
+ * This specifies the max altitude that you would like Sunlight adjustments to occur for
+ * sunrise and sunset calculations.
+ *
+ * @param maxAltitude The max altitude is specified in meters.
+ */
+ void setMaxAltitudeToDoSunriseSunsetColorAdjustment(ossim_float64 maxAltitude,
+ bool useFading=true);
+
+ /**
+ * @return the reference value used to identify when to use the eye's altitude to adjust the sun color
+ * used for shading.
+ */
+ ossim_float64 maxAltitudeToDoSunriseSunsetColorAdjustment()const;
+
+ /**
+ * This is an intensity/brightness factor multiplied by the sky color based on sun elevation angle
+ * with respect to the eye. The table is a pair of values where the first value is the elevation angle
+ * and the second value is the intensity. This table is used to do a bilinear interpolation of the brightness
+ * factor applied to the current sky color.
+ *
+ * skyColor*brightness
+ *
+ * where brightness is calculated form the passed in table.
+ *
+ * @param table a std::map of values that takes pairs elevation angle in degrees and brightness factor.
+ */
+ void setSkyColorAdjustmentTable(IntensityTableType& table);
+
+ /**
+ * @return the adjustment table used to modify the sky color. This is a table of elevation angles in degrees and
+ * brightness factors used to attenuate the skycolor.
+ */
+ const IntensityTableType* skyColorAdjustmentTable()const;
+
+ void setBaseSkyColor(const osg::Vec3d& color);
+ osg::Vec3d getBaseSkyColor()const;
+
+ void setBaseFogColor(const osg::Vec3d& color);
+ osg::Vec3d getBaseFogColor()const;
+
+ /**
+ *
+ * This mirrors the GL fog. You can currently have LINEAR, EXP, and EXP2 fog affects. @see Open gl for further information on
+ * the GL fog paramters. LINEAR uses the near and far to set fog attenuation the others attenuate based on distance.
+ *
+ */
+ void setFogMode(FogMode mode);
+
+ /**
+ * Sets the near plane where the fog begins.
+ *
+ * @param value the near plane in meters.
+ */
+ void setFogNear(ossim_float64 value);
+
+ /**
+ * Set the far plane where the fog ends. This is automatically set based on visibility.
+ *
+ * @param value The far plane value in meters.
+ */
+ void setFogFar(ossim_float64 value);
+
+ /**
+ * Density is automatically calculated based on visibility.
+ *
+ * @param value The density value to use. This should e set after the visibility is set.
+ */
+ void setFogDensity(ossim_float64 value);
+
+ /**
+ * Allows one to enable and disable fog in the scene.
+ *
+ * @param flag enables and disables the fog. Pass in true to enable and false
+ * to disable.
+ */
+ void setFogEnableFlag(bool flag);
+
+ /**
+ * Resizes the list to the specified number of cloud layers.
+ *
+ * @param numberOfLayers The number of cloud layers to resize the list to.
+ */
+ void setNumberOfCloudLayers(ossim_uint32 numberOfLayers);
+
+ void removeClouds(ossim_uint32 idx, ossim_uint32 count=1);
+ /**
+ * @param idx The index of the cloud layer to return.
+ * @return The cloud layer specified at idx. If idx is out of
+ * range then a value of null or 0 is returned.
+ */
+ ossimPlanetCloudLayer* cloudLayer(ossim_uint32 idx);
+
+ /**
+ * @return the number of cloud layers
+ */
+ ossim_uint32 numberOfCloudLayers()const;
+
+ /**
+ * This is a utility method that allows one to create a patch of clouds centered
+ * at the give lat lon height. In short, we shift the creation of the patch to lat lon height
+ * to 0,0,0 so the patch is square and then use a Matrix transform to move it to a new location defined
+ * by the center lat lon height. The seed, coverange and sharpness are exposed to give you some
+ * control over the texture generated. The seed is used to initialize the random number generator so you should
+ * be able to give the same paramters and generate the same texture. The coverage and sharpness are used to control
+ * how much clouds there are and how soft they appear. For example coverage of say 20 and sharpness of .96 gives a nice
+ * look. If you want them to be more overcast and softer, then increase the coverage to say 150 and the sharpness to around
+ * .99.
+ *
+ * @param cloudLayerIndex The cloud layer to create a patch for.
+ * @param theCenterLatLonHeight The center point to place the cloud patch.
+ * @param numberOfMeshSamples This is square so a value of 128 will
+ * create a mesh sample of 128x128.
+ * @param patchSizeInDegrees Defines the patch size in depgrees.
+ * @param seed This is the seed value used to generate a cloud texture.
+ * @param coverage This is used to generate a texture. This value is not a percentage
+ * and is a value to controll the way the clouds look.
+ * @param sharpness The closer the value is to 1.0 the softer the clouds and the closer you go to
+ * 0 the harder the clouds look.
+ */
+ void createCloudPatch(ossim_uint32 cloudLayerIndex,
+ const osg::Vec3d& theCenterLatLonHeight,
+ ossim_float64 numberOfMeshSamples,
+ ossim_float64 patchSizeInDegrees,
+ ossim_uint64 seed,
+ ossim_float64 coverage,
+ ossim_float64 sharpness);
+
+ void createGlobalCloud(ossim_uint32 cloudLayerIndex,
+ ossim_float64 altitude,
+ ossim_float64 numberOfMeshSamples,
+ ossim_uint64 seed,
+ ossim_float64 coverage,
+ ossim_float64 sharpness);
+
+ virtual osg::BoundingSphere computeBound() const;
+
+protected:
+ class EphemerisData;
+ /**
+ * This is used to hide the gpstk library we are using. This way we can conditionally compile
+ * out.
+ */
+ EphemerisData* theEphemerisData;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetExport.h b/ossimPlanet/include/ossimPlanet/ossimPlanetExport.h
new file mode 100644
index 0000000..7a03871
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetExport.h
@@ -0,0 +1,60 @@
+/* -*-c++-*- libwms - Copyright (C) since 2004 Garrett Potts
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the libwms Public License (WMSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * libwms Public License for more details.
+*/
+#ifndef ossimPlanetExport_HEADER
+#define ossimPlanetExport_HEADER
+// define used to include in API which is being fazed out
+// if you can compile your apps with this turned off you are
+// well placed for compatablity with future versions.
+#define USE_DEPRECATED_API
+
+#if defined(_MSC_VER)
+ #pragma warning( disable : 4244 )
+ #pragma warning( disable : 4251 )
+ #pragma warning( disable : 4267 )
+ #pragma warning( disable : 4275 )
+ #pragma warning( disable : 4290 )
+ #pragma warning( disable : 4786 )
+ #pragma warning( disable : 4305 )
+#endif
+
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
+# ifdef OSSIMPLANET_LIBRARY
+# define OSSIMPLANET_EXPORT __declspec(dllexport)
+# define OSSIMPLANET_DLL OSSIMPLANET_EXPORT
+# else
+# define OSSIMPLANET_EXPORT __declspec(dllimport)
+# define OSSIMPLANET_DLL OSSIMPLANET_EXPORT
+# endif /* OSSIMPLANET_LIBRARY */
+#else
+# define OSSIMPLANET_EXPORT
+# define OSSIMPLANET_DLL OSSIMPLANET_EXPORT
+#endif
+
+// set up define for whether member templates are supported by VisualStudio compilers.
+#ifdef _MSC_VER
+# if (_MSC_VER >= 1300)
+# define __STL_MEMBER_TEMPLATES
+# endif
+#endif
+
+/* Define NULL pointer value */
+
+#ifndef NULL
+ #ifdef __cplusplus
+ #define NULL 0
+ #else
+ #define NULL ((void *)0)
+ #endif
+#endif
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetExtents.h b/ossimPlanet/include/ossimPlanet/ossimPlanetExtents.h
new file mode 100644
index 0000000..c213bb5
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetExtents.h
@@ -0,0 +1,351 @@
+#ifndef ossimPlanetExtents_HEADER
+#define ossimPlanetExtents_HEADER
+#include <osg/Referenced>
+#include <ossim/base/ossimDate.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/mkUtils.h>
+
+class OSSIMPLANET_DLL ossimPlanetExtents : public osg::Referenced
+{
+public:
+ ossimPlanetExtents()
+ :osg::Referenced(),
+ theMinLon(-180.0),
+ theMaxLon(180.0),
+ theMinLat(-90.0),
+ theMaxLat(90.0),
+ theMinScale(0.0),
+ theMaxScale(1.0/DBL_EPSILON),
+ theMinHeight(-(1.0/DBL_EPSILON)+1.0),
+ theMaxHeight(1.0/DBL_EPSILON),
+ theMinDate(1, 1, 1),
+ theMaxDate(12, 31, 9999)
+ {
+ }
+ ossimPlanetExtents(const ossimPlanetExtents& src)
+ :osg::Referenced(),
+ theMinLon(src.theMinLon),
+ theMaxLon(src.theMaxLon),
+ theMinLat(src.theMinLat),
+ theMaxLat(src.theMaxLat),
+ theMinScale(src.theMinScale),
+ theMaxScale(src.theMaxScale),
+ theMinHeight(src.theMinHeight),
+ theMaxHeight(src.theMaxHeight),
+ theMinDate(src.theMinDate),
+ theMaxDate(src.theMaxDate)
+ {
+ }
+ ossimPlanetExtents* clone()const
+ {
+ return new ossimPlanetExtents(*this);
+ }
+ void setMinLatLon(double lat,
+ double lon)
+ {
+ theMinLat = lat;
+ theMinLon = lon;
+ }
+
+ void setMaxLatLon(double lat, double lon)
+ {
+ theMaxLat = lat;
+ theMaxLon = lon;
+ }
+ void setMinMaxLatLon(double minLat, double minLon,
+ double maxLat, double maxLon)
+ {
+ theMinLat = ossim::min(minLat, maxLat);
+ theMaxLat = ossim::max(minLat, maxLat);
+ theMinLon = ossim::min(minLon, maxLon);
+ theMaxLon = ossim::max(minLon, maxLon);
+ }
+ void setMinMaxHeight(double minHeight, double maxHeight)
+ {
+ theMinHeight = ossim::min(minHeight, maxHeight);
+ theMaxHeight = ossim::max(minHeight, maxHeight);
+ }
+ void setMinMaxScale(double minScale,
+ double maxScale)
+ {
+ theMinScale = ossim::min(minScale, maxScale);
+ theMaxScale = ossim::max(minScale, maxScale);
+ }
+ bool intersectsLatLon(const double& minLat, const double& minLon,
+ const double& maxLat, const double& maxLon)const
+ {
+ double tempMinLon = ossim::max(theMinLon, minLon);
+ double tempMaxLon = ossim::min(theMaxLon, maxLon);
+ double tempMinLat = ossim::max(theMinLat, minLat);
+ double tempMaxLat = ossim::min(theMaxLat, maxLat);
+
+ return ((tempMinLon <= tempMaxLon)&&(tempMinLat<=tempMaxLat));
+
+ }
+ bool intersectsLatLon(const ossimPlanetExtents& extents)const
+ {
+ return intersectsLatLon(extents.theMinLat, extents.theMinLon,
+ extents.theMaxLat, extents.theMaxLon);
+ }
+
+ bool intersectsHeight(const double& minHeight, const double& maxHeight)const
+ {
+ return (ossim::max(minHeight,
+ theMinHeight) <=
+ ossim::min(maxHeight,
+ theMaxHeight));
+ }
+ bool intersectsHeight(const ossimPlanetExtents& extents)const
+ {
+ return intersectsHeight(extents.theMinHeight,
+ extents.theMaxHeight);
+ }
+ bool intersectsScale(const double& minScale,
+ const double& maxScale)const
+ {
+ return (ossim::max(minScale,
+ theMinScale) <=
+ ossim::min(maxScale,
+ theMaxScale));
+ }
+
+ bool intersectsScale(const ossimPlanetExtents& extents)const
+ {
+ return intersectsScale(extents.theMinScale,
+ extents.theMaxScale);
+ }
+
+ bool intersectsModifiedJulianDate(const double& minDate,
+ const double& maxDate)const
+ {
+ return (ossim::max(minDate, theMinDate.getModifiedJulian()) <=
+ ossim::min(maxDate, theMaxDate.getModifiedJulian()));
+ }
+ bool intersectsDate(const ossimPlanetExtents& extents)const
+ {
+ return intersectsModifiedJulianDate(extents.theMinDate.getModifiedJulian(),
+ extents.theMaxDate.getModifiedJulian());
+ }
+
+ bool equal(osg::ref_ptr<ossimPlanetExtents> extents)const
+ {
+ if(extents.valid())
+ {
+ return equal(*extents.get());
+ }
+ return false;
+ }
+ bool equal(const ossimPlanetExtents& extents)const
+ {
+ return (ossim::almostEqual(theMinLon, extents.theMinLon, DBL_EPSILON)&&
+ ossim::almostEqual(theMaxLon, extents.theMaxLon, DBL_EPSILON)&&
+ ossim::almostEqual(theMinLat, extents.theMinLat, DBL_EPSILON)&&
+ ossim::almostEqual(theMaxLat, extents.theMaxLat, DBL_EPSILON)&&
+ ossim::almostEqual(theMinScale, extents.theMinScale, DBL_EPSILON)&&
+ ossim::almostEqual(theMaxScale, extents.theMaxScale, DBL_EPSILON)&&
+ ossim::almostEqual(theMinHeight, extents.theMinHeight, DBL_EPSILON)&&
+ ossim::almostEqual(theMaxHeight, extents.theMaxHeight, DBL_EPSILON)&&
+ (theMinDate == extents.theMinDate)&&
+ (theMaxDate == extents.theMaxDate));
+ }
+ bool intersects(const ossimPlanetExtents& extents)const
+ {
+ return (intersectsDate(extents)&&
+ intersectsScale(extents)&&
+ intersectsHeight(extents)&&
+ intersectsLatLon(extents));
+ }
+ double getMinLat()const
+ {
+ return theMinLat;
+ }
+ double getMinLon()const
+ {
+ return theMinLon;
+ }
+ double getMaxLat()const
+ {
+ return theMaxLat;
+ }
+ double getMaxLon()const
+ {
+ return theMaxLon;
+ }
+ double getMinScale()const
+ {
+ return theMinScale;
+ }
+ double getMaxScale()const
+ {
+ return theMaxScale;
+ }
+ double getMinHeight()const
+ {
+ return theMinHeight;
+ }
+ double getMaxHeight()const
+ {
+ return theMaxHeight;
+ }
+ const ossimDate& getMinDate()const
+ {
+ return theMinDate;
+ }
+ const ossimDate& getMaxDate()const
+ {
+ return theMaxDate;
+ }
+
+ void combineMinMaxLatLon(const double& minLat,
+ const double& minLon,
+ const double& maxLat,
+ const double& maxLon)
+ {
+ theMinLat = ossim::min(minLat, theMinLat);
+ theMinLon = ossim::min(minLon, theMinLon);
+ theMaxLat = ossim::max(maxLat, theMaxLat);
+ theMaxLon = ossim::max(maxLon, theMaxLon);
+ }
+ void combineHeights(const double& minHeight,
+ const double& maxHeight)
+ {
+ theMaxHeight = ossim::max(maxHeight, theMaxHeight);
+ theMinHeight = ossim::min(minHeight, theMinHeight);
+ }
+ void combineScale(const double& minScale,
+ const double& maxScale)
+ {
+ theMinScale = ossim::min(theMinScale, minScale);
+ theMaxScale = ossim::max(theMaxScale, maxScale);
+ }
+ void combineDate(const ossimDate& minDate,
+ const ossimDate& maxDate)
+ {
+ if(minDate.getModifiedJulian() < theMinDate.getModifiedJulian())
+ {
+ theMinDate = minDate;
+ }
+ if(maxDate.getModifiedJulian() > theMaxDate.getModifiedJulian())
+ {
+ theMaxDate = maxDate;
+ }
+
+ }
+ void combine(const ossimPlanetExtents* extents)
+ {
+ if(!extents) return;
+ combineMinMaxLatLon(extents->theMinLat,
+ extents->theMinLon,
+ extents->theMaxLat,
+ extents->theMaxLon);
+ combineHeights(extents->theMinHeight,
+ extents->theMaxHeight);
+ combineScale(extents->theMinScale,
+ extents->theMaxScale);
+ combineDate(extents->theMinDate,
+ extents->theMaxDate);
+
+ }
+ ossimRefPtr<ossimXmlNode> saveXml()const
+ {
+ ossimRefPtr<ossimXmlNode> result = new ossimXmlNode();
+ result->setTag("ossimPlanetExtents");
+ ossimRefPtr<ossimXmlNode> minDate = new ossimXmlNode();
+ ossimRefPtr<ossimXmlNode> maxDate = new ossimXmlNode();
+ result->addChildNode("minLat", ossimString::toString(theMinLat));
+ result->addChildNode("maxLat", ossimString::toString(theMaxLat));
+ result->addChildNode("minLon", ossimString::toString(theMinLon));
+ result->addChildNode("maxLon", ossimString::toString(theMaxLon));
+ result->addChildNode("minScale", ossimString::toString(theMinScale));
+ result->addChildNode("maxScale", ossimString::toString(theMaxScale));
+ result->addChildNode("minHeight", ossimString::toString(theMinHeight));
+ result->addChildNode("maxHeight", ossimString::toString(theMaxHeight));
+
+ minDate->setTag("minDate");
+ maxDate->setTag("maxDate");
+ minDate->addChildNode(theMinDate.saveXml().get());
+ maxDate->addChildNode(theMaxDate.saveXml().get());
+
+ result->addChildNode(minDate.get());
+ result->addChildNode(maxDate.get());
+
+ return result.get();
+ }
+ bool loadXml(ossimRefPtr<ossimXmlNode> extentsNode)
+ {
+ if(!extentsNode.valid()) return false;
+ bool result = true;
+
+ ossimRefPtr<ossimXmlNode> minLat = extentsNode->findFirstNode("minLat");
+ ossimRefPtr<ossimXmlNode> maxLat = extentsNode->findFirstNode("maxLat");
+ ossimRefPtr<ossimXmlNode> minLon = extentsNode->findFirstNode("minLon");
+ ossimRefPtr<ossimXmlNode> maxLon = extentsNode->findFirstNode("maxLon");
+ ossimRefPtr<ossimXmlNode> minScale = extentsNode->findFirstNode("minScale");
+ ossimRefPtr<ossimXmlNode> maxScale = extentsNode->findFirstNode("maxScale");
+ ossimRefPtr<ossimXmlNode> minHeight = extentsNode->findFirstNode("minHeight");
+ ossimRefPtr<ossimXmlNode> maxHeight = extentsNode->findFirstNode("maxHeight");
+ ossimRefPtr<ossimXmlNode> minDate = extentsNode->findFirstNode("minDate");
+ ossimRefPtr<ossimXmlNode> maxDate = extentsNode->findFirstNode("maxDate");
+
+ if(minLat.valid()&&maxLat.valid()&&
+ minLon.valid()&&maxLon.valid()&&
+ minScale.valid()&&maxScale.valid()&&
+ minHeight.valid()&&maxHeight.valid()&&
+ minDate.valid()&&maxDate.valid())
+ {
+ theMinLat = minLat->getText().toDouble();
+ theMaxLat = maxLat->getText().toDouble();
+ theMinLon = minLon->getText().toDouble();
+ theMaxLon = maxLon->getText().toDouble();
+ theMinScale = minScale->getText().toDouble();
+ theMaxScale = maxScale->getText().toDouble();
+ theMinHeight = minHeight->getText().toDouble();
+ theMaxHeight = maxHeight->getText().toDouble();
+ if(!theMinDate.loadXml(minDate.get()))
+ {
+ result = false;
+ }
+ if(!theMaxDate.loadXml(maxDate.get()))
+ {
+ result = false;
+ }
+ }
+ else
+ {
+ result = false;
+ }
+
+ return result;
+ }
+ ossimString toString()const
+ {
+ ossimString result;
+
+ result += "theMinLon: " + ossimString::toString(theMinLon) + "\n";
+ result += "theMaxLon: " + ossimString::toString(theMaxLon) + "\n";
+ result += "theMinLat: " + ossimString::toString(theMinLat) + "\n";
+ result += "theMaxLat: " + ossimString::toString(theMaxLat) + "\n";
+ result += "theMinScale: " + ossimString::toString(theMinScale) + "\n";
+ result += "theMaxScale: " + ossimString::toString(theMaxScale) + "\n";
+ result += "theMinHeight: " + ossimString::toString(theMinHeight) + "\n";
+ result += "theMaxHeight: " + ossimString::toString(theMaxHeight);
+ return result;
+ }
+protected:
+ ~ossimPlanetExtents()
+ {
+ }
+ double theMinLon;
+ double theMaxLon;
+ double theMinLat;
+ double theMaxLat;
+ double theMinScale;
+ double theMaxScale;
+ double theMinHeight;
+ double theMaxHeight;
+ ossimDate theMinDate;
+ ossimDate theMaxDate;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetFadeText.h b/ossimPlanet/include/ossimPlanet/ossimPlanetFadeText.h
new file mode 100644
index 0000000..2aa9d08
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetFadeText.h
@@ -0,0 +1,77 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#ifndef ossimPlanetFadeText_HEADER
+#define ossimPlanetFadeText_HEADER 1
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osgText/Text>
+#include <ossim/base/ossimConstants.h>
+#include <osg/ClusterCullingCallback>
+
+class OSSIMPLANET_DLL ossimPlanetFadeText : public osgText::Text
+{
+public:
+ ossimPlanetFadeText();
+ ossimPlanetFadeText(const Text& text,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ META_Object(osgText, ossimPlanetFadeText)
+
+
+ /**
+ * Set the speed that the alpha value changes as the text is occluded or becomes visible.
+ *
+ */
+ void setFadeSpeed(float speed) { theFadeSpeed = speed; }
+ float fadeSpeed()const{return theFadeSpeed;}
+ void setVisibleFlag(bool visible){theVisibleFlag = visible;}
+ bool visibleFlag()const{return theVisibleFlag;}
+ float opacity()const{return theCurrentOpacity;}
+ void setOpacity(float value){theCurrentOpacity = value;}
+ void setClusterCullingCallback(osg::ref_ptr<osg::ClusterCullingCallback> callback)
+ {
+ theClusterCull = callback;
+ }
+ osg::ref_ptr<osg::ClusterCullingCallback> clusterCullingCallback()
+ {
+ return theClusterCull;
+ }
+ const osg::ref_ptr<osg::ClusterCullingCallback> clusterCullingCallback()const
+ {
+ return theClusterCull;
+ }
+ /** Draw the text.*/
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
+
+protected:
+
+ virtual ~ossimPlanetFadeText() {}
+
+ void init();
+
+ struct FadeTextUpdateCallback;
+ struct FadeTextCullCallback;
+ friend struct FadeTextUpdateCallback;
+ friend struct FadeTextCullCallback;
+
+ float theFadeSpeed;
+ float theCurrentOpacity;
+ bool theVisibleFlag;
+ ossim_uint32 theFrameNumber;
+ osg::ref_ptr<osg::ClusterCullingCallback> theClusterCull;
+
+ osg::Vec4d theForegroundColor;
+ osg::Vec4d theBackgroundColor;
+ // mutable ViewBlendColourMap _viewBlendColourMap;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.h
new file mode 100644
index 0000000..4ac6ca3
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.h
@@ -0,0 +1,63 @@
+#ifndef ossimPlanetGeneralRasterElevationDatabase_HEADER
+#define ossimPlanetGeneralRasterElevationDatabase_HEADER
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <osg/Timer>
+#include <ossim/elevation/ossimGeneralRasterElevHandler.h>
+class OSSIMPLANET_DLL ossimPlanetGeneralRasterElevationDatabase : public ossimPlanetElevationDatabase
+{
+public:
+ ossimPlanetGeneralRasterElevationDatabase();
+ ossimPlanetGeneralRasterElevationDatabase(const ossimPlanetGeneralRasterElevationDatabase& src);
+ virtual ~ossimPlanetGeneralRasterElevationDatabase();
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ virtual void resetStats()const;
+ virtual ossimPlanetTextureLayerStateCode open(const std::string& location);
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+
+protected:
+ class GeneralRasterInfo : public osg::Referenced
+ {
+ public:
+ double theMinLat, theMinLon, theMaxLat, theMaxLon;
+ std::string theFilename;
+ ossimRefPtr<ossimGeneralRasterElevHandler> theGeneralRasterHandler;
+ bool theOpenFlag;
+ osg::Timer_t theTimeStamp;
+ };
+ typedef std::vector<osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> > GeneralRasterFilePointerList;
+
+ osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> getHandlerInfo(const double& lat,
+ const double& lon);
+ //void shrinkFilePointers();
+/* ossimFilename buildFilename(double lat, double lon)const; */
+/* osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::SrtmInfo> findSrtmInfo(const std::string& srtmName); */
+
+ std::string theLocation;
+ mutable bool theOpenFlag;
+ ossim_uint32 theMaxOpenFiles;
+ ossim_uint32 theMinOpenFiles;
+ GeneralRasterFilePointerList theFilePointers;
+ mutable ossim_int32 theCurrentInfoIdx;
+/* ossimRefPtr<ossimMapProjection> theProjection; */
+/* ossimRefPtr<ossimImageRenderer> theRenderer; */
+/* ossimRefPtr<ossimOrthoImageMosaic> theMosaic; */
+/* ossim_float32 theNullHeightValue; */
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetGeoRefModel.h b/ossimPlanet/include/ossimPlanet/ossimPlanetGeoRefModel.h
new file mode 100644
index 0000000..2539328
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetGeoRefModel.h
@@ -0,0 +1,370 @@
+#ifndef ossimPlanetGeoRefModel_HEADER
+#define ossimPlanetGeoRefModel_HEADER
+#include <osg/Referenced>
+#include <osg/Vec3d>
+#include <osg/CoordinateSystemNode>
+#include <ossim/base/ossimLsrSpace.h>
+#include <ossim/base/ossimMatrix4x4.h>
+#include <ossim/base/ossimEllipsoid.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimGeoid.h>
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimEcefVector.h>
+#include <ossim/base/ossimGeoidManager.h>
+#include <ossim/elevation/ossimElevManager.h>
+
+class OSSIMPLANET_DLL ossimPlanetGeoRefModel : public osg::Referenced
+{
+public:
+ ossimPlanetGeoRefModel()
+ :theGeoid(ossimGeoidManager::instance()->findGeoidByShortName("geoid1996", false))
+ {
+ }
+ virtual void latLonHeightToXyz(const osg::Vec3d& input,
+ osg::Vec3d& output)const=0;
+ virtual void xyzToLatLonHeight(const osg::Vec3d& input,
+ osg::Vec3d& output)const=0;
+ virtual void latLonHeightMslToXyz(const osg::Vec3d& input,
+ osg::Vec3d& output)
+ {
+ osg::Vec3d llh(input);
+ mslToEllipsoidal(llh);
+ latLonHeightToXyz(llh, output);
+ }
+ virtual void xyzToLatLonHeightMsl(const osg::Vec3d& input,
+ osg::Vec3d& output)
+ {
+ xyzToLatLonHeight(input, output);
+ ellipsoidalToMsl(output);
+ }
+ virtual void forward(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ latLonHeightToXyz(input, output);
+ }
+ virtual void inverse(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ xyzToLatLonHeight(input, output);
+ }
+ virtual void normal(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ output = input;
+ output.normalize();
+ }
+
+ /**
+ * This will take a lat lon height and shift the height to the ellipsoid
+ */
+ virtual void mslToEllipsoidal(osg::Vec3d& llh)
+ {
+ llh[2] += getGeoidOffset(llh[0],llh[1]);
+ }
+
+ /**
+ * This will take a lat lon height and shift the height to the Mean Sea Level.
+ * This assumes the height you passed in was Ellipsoidal
+ */
+ virtual void ellipsoidalToMsl(osg::Vec3d& llh)
+ {
+ llh[2] -= getGeoidOffset(llh[0],llh[1]);
+ }
+ virtual double getHeightAboveMsl(const double& lat, const double& lon)
+ {
+ double result = ossimElevManager::instance()->getHeightAboveMSL(ossimGpt(lat, lon));
+ if(ossim::isnan(result))
+ {
+ result = 0.0;
+ }
+ return result;
+ }
+ virtual double getGeoidOffset(const double& lat, const double& lon)
+ {
+ double result = 0.0;
+ if(theGeoid.valid())
+ {
+ result = theGeoid->offsetFromEllipsoid(ossimGpt(lat,lon));
+ if(ossim::isnan(result))
+ {
+ result = 0.0;
+ }
+ }
+ return result;
+ }
+ virtual double getHeightAboveEllipsoid(const double& lat, const double& lon)
+ {
+ double result = ossimElevManager::instance()->getHeightAboveEllipsoid(ossimGpt(lat, lon));
+ if(ossim::isnan(result))
+ {
+ if(theGeoid.valid())
+ {
+ result = theGeoid->offsetFromEllipsoid(ossimGpt(lat,lon));
+ if(ossim::isnan(result))
+ {
+ result = 0.0;
+ }
+ }
+ else
+ {
+ result = 0.0;
+ }
+ }
+
+ return result;
+ }
+ virtual void lsrMatrix(const osg::Vec3d& /*latLonHeight*/,
+ osg::Matrixd& output,
+ double /*heading*/=0.0,
+ bool /*rotationOnlyFlag*/=false)const
+ {
+ output = osg::Matrixd();
+ }
+ virtual void orientationLsrMatrix(osg::Matrixd& result,
+ const osg::Vec3d& llh,
+ double h, double p, double r)const
+ {
+ lsrMatrix(llh, result, 0.0);
+
+ NEWMAT::Matrix orien = ossimMatrix4x4::createRotationZMatrix(h, OSSIM_RIGHT_HANDED)*
+ ossimMatrix4x4::createRotationXMatrix(p, OSSIM_LEFT_HANDED)*
+ ossimMatrix4x4::createRotationYMatrix(r, OSSIM_LEFT_HANDED);
+ osg::Matrixd tempM(orien[0][0], orien[1][0], orien[2][0], 0.0,
+ orien[0][1], orien[1][1], orien[2][1], 0.0,
+ orien[0][2], orien[1][2], orien[2][2], 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+
+ result = tempM*result;
+ }
+/* virtual void computeLocalToWorldTransform(const osg::Vec3d& input, */
+/* osg::Matrixd& output)const=0; */
+ virtual double calculateUnnormalizedLengthXyz(const osg::Vec3d& p1,
+ const osg::Vec3d& p2)const
+ {
+ return calculateUnnormalizedLength((p1-p2).length());
+ }
+ virtual double calculateUnnormalizedLength(double delta)const
+ {
+ return getNormalizationScale()*delta;
+ }
+ virtual double getNormalizationScale()const
+ {
+ return 1.0;
+ }
+ virtual double getInvNormalizationScale()const
+ {
+ return 1.0;
+ }
+ const ossimRefPtr<ossimGeoid> geoid()const
+ {
+ return theGeoid;
+ }
+ void setGeoid(ossimRefPtr<ossimGeoid> geoid)
+ {
+ theGeoid = geoid.get();
+ }
+protected:
+ ossimRefPtr<ossimGeoid> theGeoid;
+
+};
+
+
+class ossimPlanetEllipsoidModel : public ossimPlanetGeoRefModel
+{
+public:
+ ossimPlanetEllipsoidModel(double radiusEquator = osg::WGS_84_RADIUS_EQUATOR,
+ double radiusPolar = osg::WGS_84_RADIUS_POLAR)
+ :theModel(radiusEquator, radiusPolar)
+ {
+ }
+
+
+ virtual void lsrMatrix(const osg::Vec3d& latLonHeight,
+ osg::Matrixd& output,
+ double heading=0.0,
+ bool rotationOnlyFlag=false)const
+ {
+ osg::Vec3d xyz;
+ ossimLsrSpace lsrSpace;
+ lsrSpace = ossimLsrSpace(ossimGpt(latLonHeight[0],
+ latLonHeight[1],
+ latLonHeight[2]),
+ heading);//,
+ if(!rotationOnlyFlag)
+ {
+ latLonHeightToXyz(latLonHeight, xyz);
+ }
+ ossimMatrix4x4 lsrMatrix(lsrSpace.lsrToEcefRotMatrix());
+ NEWMAT::Matrix compositeMatrix = lsrMatrix.getData();
+/* compositeMatrix = compositeMatrix.t(); */
+ output = osg::Matrixd(compositeMatrix[0][0], compositeMatrix[1][0], compositeMatrix[2][0], 0.0,
+ compositeMatrix[0][1], compositeMatrix[1][1], compositeMatrix[2][1], 0.0,
+ compositeMatrix[0][2], compositeMatrix[1][2], compositeMatrix[2][2], 0.0,
+ xyz[0], xyz[1], xyz[2], 1.0);
+ }
+ virtual void latLonHeightToXyz(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ theModel.latLonHeightToXYZ(input[0],
+ input[1],
+ input[2],
+ output[0],
+ output[1],
+ output[2]);
+ }
+ virtual void xyzToLatLonHeight(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ theModel.XYZToLatLonHeight(input[0],
+ input[1],
+ input[2],
+ output[0],
+ output[1],
+ output[2]);
+ }
+ virtual void normal(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ ossimEcefPoint location(input[0], input[1], input[2]);
+ ossimEcefVector gradient;
+ theModel.gradient(location, gradient);
+ output[0] = gradient.x();
+ output[1] = gradient.y();
+ output[2] = gradient.z();
+ }
+protected:
+ ossimEllipsoid theModel;
+/* osg::ref_ptr<osg::EllipsoidModel> theModel; */
+};
+
+class ossimPlanetNormalizedEllipsoidModel : public ossimPlanetEllipsoidModel
+{
+public:
+ ossimPlanetNormalizedEllipsoidModel(double radiusEquator = osg::WGS_84_RADIUS_EQUATOR,
+ double radiusPolar = osg::WGS_84_RADIUS_POLAR)
+ :ossimPlanetEllipsoidModel(radiusEquator, radiusPolar)
+ {
+ theNormalizationScale = osg::WGS_84_RADIUS_EQUATOR;
+ theInvNormalizationScale = 1.0/osg::WGS_84_RADIUS_EQUATOR;
+ }
+
+ virtual void latLonHeightToXyz(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ theModel.latLonHeightToXYZ(input[0],
+ input[1],
+ input[2],
+ output[0],
+ output[1],
+ output[2]);
+ output[0]*=theInvNormalizationScale;
+ output[1]*=theInvNormalizationScale;
+ output[2]*=theInvNormalizationScale;
+
+ }
+ virtual void xyzToLatLonHeight(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+
+ theModel.XYZToLatLonHeight(input[0]*theNormalizationScale,
+ input[1]*theNormalizationScale,
+ input[2]*theNormalizationScale,
+ output[0],
+ output[1],
+ output[2]);
+ }
+ virtual void lsrMatrix(const osg::Vec3d& latLonHeight,
+ osg::Matrixd& output,
+ bool rotationOnlyFlag=false)const
+ {
+ osg::Vec3d xyz;
+ ossimLsrSpace lsrSpace;
+ lsrSpace = ossimLsrSpace(ossimGpt(latLonHeight[0],
+ latLonHeight[1],
+ latLonHeight[2]),
+ 0.0);//,
+ if(!rotationOnlyFlag)
+ {// make sure that the x,y,z are normalized.
+ latLonHeightToXyz(latLonHeight, xyz);
+ xyz[0] *= theNormalizationScale;
+ xyz[1] *= theNormalizationScale;
+ xyz[2] *= theNormalizationScale;
+ }
+ ossimMatrix4x4 lsrMatrix(lsrSpace.lsrToEcefRotMatrix());
+ NEWMAT::Matrix compositeMatrix = lsrMatrix.getData();
+/* compositeMatrix = compositeMatrix.t(); */
+ output = osg::Matrixd(compositeMatrix[0][0], compositeMatrix[1][0], compositeMatrix[2][0], 0.0,
+ compositeMatrix[0][1], compositeMatrix[1][1], compositeMatrix[2][1], 0.0,
+ compositeMatrix[0][2], compositeMatrix[1][2], compositeMatrix[2][2], 0.0,
+ xyz[0], xyz[1], xyz[2], 1.0);
+ }
+ virtual double getNormalizationScale()const
+ {
+ return theNormalizationScale;
+ }
+ virtual double getInvNormalizationScale()const
+ {
+ return theInvNormalizationScale;
+ }
+
+protected:
+ double theNormalizationScale;
+ double theInvNormalizationScale;
+};
+
+#if 0
+class ossimPlanetFlatLandModel : public ossimPlanetLandModel
+{
+public:
+ ossimPlanetFlatLandModel(){}
+ virtual void latLonHeightToXyz(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ output[0] = input[1];
+ output[1] = input[0];
+ output[2] = input[2];
+ }
+ virtual void computeLocalToWorldTransform(const osg::Vec3d& /* input */,
+ osg::Matrixd& /* output */)const
+ {
+ // left blank for now so the matrix will not change
+ }
+ virtual void xyzToLatLonHeight(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ output[0] = input[1];
+ output[1] = input[0];
+ output[2] = input[2];
+ }
+ virtual void normal(const osg::Vec3d& input,
+ osg::Vec3d& output)const
+ {
+ if(theNormalModel.valid())
+ {
+ osg::Vec3d tempVec;
+ osg::Vec3d tempVec2;
+ xyzToLatLonHeight(input, tempVec);
+ theNormalModel->forward(tempVec, tempVec2);
+ theNormalModel->normal(tempVec2,
+ output);
+ output[0] *=-1.0;
+ output[1] *=-1.0;
+ output[2] *=-1.0;
+ }
+ else
+ {
+ output[0] = 0.0;
+ output[1] = 0.0;
+ output[2] = -1.0;
+ }
+ }
+ virtual void changeNormalModel(osg::ref_ptr<ossimPlanetLandModel> normalModel)
+ {
+ theNormalModel = normalModel;
+ }
+
+ osg::ref_ptr<ossimPlanetLandModel> theNormalModel;
+};
+#endif
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetGeocoder.h b/ossimPlanet/include/ossimPlanet/ossimPlanetGeocoder.h
new file mode 100644
index 0000000..f411b05
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetGeocoder.h
@@ -0,0 +1,82 @@
+#ifndef ossimPlanetGeocoder_HEADER
+#define ossimPlanetGeocoder_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetGoecoder : public osg::Referenced
+{
+public:
+ class OSSIMPLANET_DLL ossimPlanetGeocoderLocation : public osg::Referenced
+ {
+ public:
+ ossimPlanetGeocoderLocation();
+
+ void setLocation(const ossimGpt& location);
+ ossimGpt getLocation()const;
+ void setName(const ossimString& name);
+ ossimString getName()const;
+ void setAddress(const ossimString& address);
+ ossimString getAddress()const;
+
+ protected:
+ ossimRefPtr<ossimXmlNode> theMetaInformation; // modeled after the GOOGLE KML
+ ossimRefPtr<ossimXmlNode> theNameNode;
+ ossimRefPtr<ossimXmlNode> thePlacemarkNode;
+ ossimRefPtr<ossimXmlNode> theAddressNode;
+ ossimRefPtr<ossimXmlNode> thePointNode;
+ ossimRefPtr<ossimXmlNode> theCoordinatesNode;
+ };
+ virtual void getLocationFromAddress(std::vector<osg::ref_ptr<ossimPlanetGeocoderLocation> >& result,
+ const ossimString& address,
+ const ossimString& city,
+ const ossimString& state,
+ const ossimString& zip,
+ const ossimString& /*country*/)const
+ {
+ ossimString location;
+ if(!address.trim().empty())
+ {
+ location += address;
+ }
+
+ if(!city.trim().empty())
+ {
+ if(!location.empty())
+ {
+ location += ",";
+ }
+ location += city;
+ }
+
+ if(!state.trim().empty())
+ {
+ if(!location.empty())
+ {
+ location += ",";
+ }
+ location += state;
+ }
+
+ if(!zip.trim().empty())
+ {
+ if(!location.empty())
+ {
+ location += ",";
+ }
+ location += zip;
+ }
+
+ getLocationFromAddress(result, location);
+
+ }
+ virtual void getLocationFromAddress(std::vector<osg::ref_ptr<ossimPlanetGeocoderLocation> >& result,
+ const ossimString& location)const=0;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetGrid.h b/ossimPlanet/include/ossimPlanet/ossimPlanetGrid.h
new file mode 100644
index 0000000..8f8e761
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetGrid.h
@@ -0,0 +1,310 @@
+#ifndef ossimPlanetGrid_HEADER
+#define ossimPlanetGrid_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetTerrainTileId.h>
+#include <ossimPlanet/ossimPlanetExtents.h>
+#include <osg/Referenced>
+#include <osg/Vec3d>
+#include <osg/Vec2d>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDrect.h>
+#include <vector>
+#include <iostream>
+
+// this is here temporarily until everyone uses the new grid interface. This will be used to
+// crate a backward comapatable grid type
+#include <ossimPlanet/ossimPlanetGridUtility.h>
+
+class OSSIMPLANET_DLL ossimPlanetGrid : public osg::Referenced
+{
+public:
+ enum IndexValues
+ {
+ LAT_IDX = 0,
+ LON_IDX = 1,
+ HGT_IDX = 2,
+ X_IDX = 0,
+ Y_IDX = 1,
+ Z_IDX = 2
+ };
+ enum ModelType
+ {
+ UNKNOWN = 0,
+ GEODETIC_MODEL = 1
+ };
+ class LocalNdcPoint
+ {
+ public:
+ LocalNdcPoint(ossim_float64 xValue=0.0,
+ ossim_float64 yValue=0.0,
+ ossim_float64 zValue=0.0)
+ {
+ setX(xValue);
+ setY(yValue);
+ setZ(zValue);
+ }
+ void setX(ossim_float64 value){theXYZ[ossimPlanetGrid::X_IDX] = value;}
+ void setY(ossim_float64 value){theXYZ[ossimPlanetGrid::Y_IDX] = value;}
+ void setZ(ossim_float64 value){theXYZ[ossimPlanetGrid::Z_IDX] = value;}
+ ossim_float64 x()const{return theXYZ[ossimPlanetGrid::X_IDX];}
+ ossim_float64 y()const{return theXYZ[ossimPlanetGrid::Y_IDX];}
+ ossim_float64 z()const{return theXYZ[ossimPlanetGrid::Z_IDX];}
+ osg::Vec3d theXYZ;
+ };
+ class GridPoint
+ {
+ public:
+ friend std::ostream& operator <<(std::ostream& out, const ossimPlanetGrid::GridPoint& point)
+ {
+ return out << "<" << point.theFace << ", " << point.theXYZ[ossimPlanetGrid::X_IDX] << ", " << point.theXYZ[ossimPlanetGrid::Y_IDX] << ", " << point.theXYZ[ossimPlanetGrid::Z_IDX] << ">";
+ }
+ GridPoint()
+ :theFace(0)
+ {
+ theXYZ[0]=0.0;
+ theXYZ[1]=0.0;
+ theXYZ[2]=0.0;
+ }
+ GridPoint(ossim_uint32 face,
+ ossim_float64 x, ossim_float64 y, ossim_float64 z=0.0)
+ :theFace(face)
+ {
+ theXYZ[ossimPlanetGrid::X_IDX]=x;
+ theXYZ[ossimPlanetGrid::Y_IDX]=y;
+ theXYZ[ossimPlanetGrid::Z_IDX]=z;
+ }
+ GridPoint(ossim_uint32 face,
+ osg::Vec3d& xyz)
+ :theFace(face),
+ theXYZ(xyz)
+ {
+ }
+ void setX(ossim_float64 value){theXYZ[ossimPlanetGrid::X_IDX] = value;}
+ void setY(ossim_float64 value){theXYZ[ossimPlanetGrid::Y_IDX] = value;}
+ void setZ(ossim_float64 value){theXYZ[ossimPlanetGrid::Z_IDX] = value;}
+ ossim_float64 x()const{return theXYZ[ossimPlanetGrid::X_IDX];}
+ ossim_float64 y()const{return theXYZ[ossimPlanetGrid::Y_IDX];}
+ ossim_float64 z()const{return theXYZ[ossimPlanetGrid::Z_IDX];}
+ ossim_uint32 face()const{return theFace;}
+ void setFace(ossim_uint32 face){theFace = face;}
+
+ ossim_uint32 theFace;
+ osg::Vec3d theXYZ;
+ };
+ class GridBound
+ {
+ public:
+ friend std::ostream& operator <<(std::ostream& out, const ossimPlanetGrid::GridBound& bound)
+ {
+ return out << "<" << bound.face() << ","
+ << bound.minx() << ", "
+ << bound.miny() << ", "
+ << bound.maxx() << ","
+ << bound.maxy() << ">";
+ }
+ ossim_float64 minx()const{return theMinx;}
+ ossim_float64 miny()const{return theMiny;}
+ ossim_float64 maxx()const{return theMinx+theWidth;}
+ ossim_float64 maxy()const{return theMiny+theHeight;}
+ ossim_float64 width()const{return theWidth;}
+ ossim_float64 height()const{return theHeight;}
+ void setFace(ossim_uint32 face){theFace = face;}
+ ossim_uint32 face()const{return theFace;}
+ ossimDrect toDrect()const
+ {
+ return ossimDrect(theMinx,
+ theMiny+theHeight,
+ theMinx+theWidth,
+ theMiny, OSSIM_RIGHT_HANDED);
+ }
+ ossim_uint32 theFace;
+ ossim_float64 theMinx;
+ ossim_float64 theMiny;
+ ossim_float64 theWidth;
+ ossim_float64 theHeight;
+ };
+ class ModelPoint
+ {
+ public:
+ friend std::ostream& operator <<(std::ostream& out, const ossimPlanetGrid::ModelPoint& point)
+ {
+ return out << "<" << point.theXYZ[ossimPlanetGrid::X_IDX] << ", " << point.theXYZ[ossimPlanetGrid::Y_IDX] << ", " << point.theXYZ[ossimPlanetGrid::Z_IDX] << ">";
+ }
+ ModelPoint()
+ {
+ theXYZ[0]=0.0;
+ theXYZ[1]=0.0;
+ theXYZ[2]=0.0;
+ }
+ ModelPoint(double x, double y, double z=0)
+ {
+ theXYZ[0] = x;
+ theXYZ[1] = y;
+ theXYZ[2] = z;
+ }
+ void setX(ossim_float64 value){theXYZ[ossimPlanetGrid::X_IDX] = value;}
+ void setY(ossim_float64 value){theXYZ[ossimPlanetGrid::Y_IDX] = value;}
+ void setZ(ossim_float64 value){theXYZ[ossimPlanetGrid::Z_IDX] = value;}
+ ossim_float64 x()const{return theXYZ[ossimPlanetGrid::X_IDX];}
+ ossim_float64 y()const{return theXYZ[ossimPlanetGrid::Y_IDX];}
+ ossim_float64 z()const{return theXYZ[ossimPlanetGrid::Z_IDX];}
+
+ osg::Vec3d theXYZ;
+ };
+ typedef std::vector<ossimPlanetTerrainTileId> TileIds;
+ typedef std::vector<ModelPoint> ModelPoints;
+ typedef std::vector<GridPoint> GridPoints;
+ typedef std::vector<GridBound> GridBounds;
+
+ ossimPlanetGrid(ossimPlanetGrid::ModelType type)
+ :theModelType(type)
+ {
+ }
+ ossimPlanetGrid::ModelType modelType()const
+ {
+ return theModelType;
+ }
+ virtual void getRootIds(TileIds &ids) const=0;
+ void getInternationalDateLineCrossings(const ossimPlanetTerrainTileId& tileid,
+ std::vector<osg::Vec2d>& minMaxPairs)const;
+ virtual bool crossesInternationalDateLine(const ossimPlanetTerrainTileId& tileId)const;
+ virtual void createModelPoints(const ossimPlanetTerrainTileId& tileId,
+ ossim_uint32 w,
+ ossim_uint32 h,
+ ModelPoints& modelPoints,
+ ossim_uint32 padding=0)const;
+ virtual void globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const=0;
+ virtual void modelToGlobalGrid(const ModelPoint& modelPoint, GridPoint& gridPoint)const=0;
+ virtual void modelBound(const ossimPlanetTerrainTileId& tileId,
+ ModelPoint& minPoint, ModelPoint& maxPoint)const;
+ virtual void localNdcToGlobalGrid(const ossimPlanetTerrainTileId& tileId, const LocalNdcPoint& localNdc, GridPoint& globalGrid)const;
+ virtual void localNdcToModel(const ossimPlanetTerrainTileId& tileId, const LocalNdcPoint& localNdc, ModelPoint& model)const;
+ virtual void numberOfTilesPerFace(ossim_uint32 lod, ossim_uint64& tilesWide, ossim_uint64& tilesHigh) const;
+ virtual void bounds(const ossimPlanetTerrainTileId& tileId, GridBound& bound)const;
+ virtual void boundsToModel(const ossimPlanetTerrainTileId& tileId,
+ ModelPoint& p0,
+ ModelPoint& p1,
+ ModelPoint& p2,
+ ModelPoint& p3)const;
+ virtual void centerGrid(const ossimPlanetTerrainTileId& tileId, GridPoint& gridPoint);
+ virtual void centerModel(const ossimPlanetTerrainTileId& tileId, ModelPoint& modelPoint);
+ virtual void widthHeight(const ossimPlanetTerrainTileId& tileId, ossim_float64& width, ossim_float64& height)const;
+ virtual void origin(const ossimPlanetTerrainTileId& tileId, GridPoint& gridPoint)const;
+
+ virtual void getUnitsPerPixel(osg::Vec2d& unitsPerPixel,
+ const ossimPlanetTerrainTileId& tileId, ossim_uint32 w, ossim_uint32 h,
+ const ossimUnitType unitType=OSSIM_METERS)const;
+ virtual bool convertToGeographicExtents(const ossimPlanetTerrainTileId& tileId,
+ ossimPlanetExtents& extents,
+ ossim_uint32 w, ossim_uint32 h)const;
+ virtual void widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId, osg::Vec2d& deltaXY)const=0;
+ virtual ossim_uint32 numberOfFaces()const=0;
+ virtual bool findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints=3)const=0;
+ virtual bool isPolar(const ossimPlanetTerrainTileId& id)const=0;
+ /**
+ *
+ */
+ virtual ossimPlanetGridUtility* newBackwardCompatableGrid(ossim_uint32 width,
+ ossim_uint32 height)const=0;
+protected:
+ ModelType theModelType;
+};
+
+class OSSIMPLANET_DLL ossimPlanetCubeGrid2 : public ossimPlanetGrid
+{
+public:
+ ossimPlanetCubeGrid2()
+ :ossimPlanetGrid(ossimPlanetGrid::GEODETIC_MODEL),
+ theEquatorialCols(4),
+ theEquatorialRows(1) // will specify the number of bands
+ {
+ }
+ virtual void getRootIds(TileIds &ids) const;
+ virtual void globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const;
+ virtual void modelToGlobalGrid(const ModelPoint& modelPoint,
+ GridPoint& gridPoint)const;
+ virtual void widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId, osg::Vec2d& deltaXY)const;
+ virtual bool findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints=3)const;
+ virtual ossim_uint32 numberOfFaces()const;
+ virtual ossimPlanetGridUtility* newBackwardCompatableGrid(ossim_uint32 width,
+ ossim_uint32 height)const;
+ virtual bool isPolar(const ossimPlanetTerrainTileId& id)const;
+
+protected:
+ virtual void globalGridToModelLat45(const GridPoint& gridPoint, ModelPoint& modelPoint)const;
+ virtual void globalGridToModelLat67_5(const GridPoint& gridPoint, ModelPoint& modelPoint)const;
+
+ ossim_uint32 theEquatorialCols;
+ ossim_uint32 theEquatorialRows;
+};
+
+class OSSIMPLANET_DLL ossimPlanetPlaneGrid2 : public ossimPlanetGrid
+{
+public:
+ ossimPlanetPlaneGrid2()
+ :ossimPlanetGrid(ossimPlanetGrid::GEODETIC_MODEL)
+ {
+ }
+ virtual void getRootIds(TileIds &ids) const;
+ virtual void globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const;
+ virtual void modelToGlobalGrid(const ModelPoint& modelPoint,
+ GridPoint& gridPoint)const;
+ virtual void widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId, osg::Vec2d& deltaXY)const;
+ virtual bool findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints=3)const;
+ virtual ossim_uint32 numberOfFaces()const;
+ virtual ossimPlanetGridUtility* newBackwardCompatableGrid(ossim_uint32 width,
+ ossim_uint32 height)const;
+ virtual bool isPolar(const ossimPlanetTerrainTileId& /*id*/)const
+ {
+ return false;
+ }
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetAdjustableCubeGrid : public ossimPlanetCubeGrid2
+{
+public:
+ enum CapLocation
+ {
+ LOW_CAP = 0, // 45 degree lat, default to Cube map
+ MEDIUM_LOW_CAP, // 67.5 degree lat
+ MEDIUM_CAP, // 78.75 degree lat
+ MEDIUM_HIGH_CAP, // 84.375 degree lat
+ HIGH_CAP // 87.1875 degree lat
+ };
+
+ ossimPlanetAdjustableCubeGrid(CapLocation location = MEDIUM_CAP);
+ virtual void setCapLocation(CapLocation location);
+ virtual void getRootIds(TileIds &ids) const;
+ virtual void globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const;
+ virtual void modelToGlobalGrid(const ModelPoint& modelPoint,
+ GridPoint& gridPoint)const;
+ virtual void widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId, osg::Vec2d& deltaXY)const;
+ virtual bool findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints=3)const;
+ virtual ossim_uint32 numberOfFaces()const;
+ virtual bool isPolar(const ossimPlanetTerrainTileId& id)const;
+
+protected:
+ CapLocation theCapLocation;
+ ossim_float64 thePolarLat;
+ ossim_float64 theUpperEquatorialBandLatDelta;
+ ossim_float64 thePolarWidth;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetGridUtility.h b/ossimPlanet/include/ossimPlanet/ossimPlanetGridUtility.h
new file mode 100644
index 0000000..3278f45
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetGridUtility.h
@@ -0,0 +1,166 @@
+#ifndef ossimPlanetGridUtility_HEADER
+#define ossimPlanetGridUtility_HEADER
+#include <ossim/base/ossimConstants.h>
+#include <osg/Referenced>
+#include "ossimPlanetExport.h"
+#include <osg/Vec3d>
+#include <vector>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+
+class OSSIMPLANET_DLL ossimPlanetGridUtility : public osg::Referenced
+{
+public:
+ enum ossimPlanetGridUtilityIndices
+ {
+ LAT = 0,
+ LON = 1,
+ HGT = 2,
+ GRIDX = 0,
+ GRIDY = 1,
+ GRIDZ = 2
+ };
+ class GridPoint
+ {
+ public:
+ // the global is a 0 to 1 for the entire face.
+ osg::Vec3d theGlobalGridPoint;
+
+ // the local is a 0 to 1 for the local row col patch. This value could be used
+ // for the texture coordinate
+ osg::Vec3d theLocalGridPoint;
+
+ // theFace this grid point corresponds to
+ ossim_uint32 theFace;
+ };
+
+ ossimPlanetGridUtility(ossim_uint32 tileWidth = 256,
+ ossim_uint32 tileHeight = 256)
+ {
+ theTileWidth = tileWidth;
+ theTileHeight = tileHeight;
+ }
+ void getGeographicLonCrossings(std::vector<osg::Vec2d>& minMaxPairs,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual bool crossesGeographicBounds(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual void getWidthHeightInDegrees(double& deltaX,
+ double& deltaY,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual void getGridSpacing(double& xSpacing,
+ double& ySpacing,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+
+ virtual void getPixelScaleAsDegrees(double& dx,
+ double& dy,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual void getPixelScaleAsMeters(double& dx,
+ double& dy,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual void getPixelScale(double& dx,
+ double& dy,
+ ossimUnitType& pixelScaleUnits,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const=0;
+
+ virtual void getLocalRowColumn(ossim_uint64& localRow,
+ ossim_uint64& localCol,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+ virtual void mapToRowCol(ossim_uint64& targetRow,
+ ossim_uint64& targetCol,
+ ossim_uint32 targetLevel,
+ ossim_uint32 srcLevel,
+ ossim_uint64 srcRow,
+ ossim_uint64 srcCol)const;
+
+ virtual ossim_uint32 getFace(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+
+
+ virtual void getNumberOfTilesWideHighPerFace(ossim_uint64 &wide,
+ ossim_uint64 &high,
+ ossim_uint32 level)const;
+
+
+ virtual ossim_uint32 getNumberOfFaces()const=0;
+
+ virtual void getCenterGridPoint(ossimPlanetGridUtility::GridPoint& point,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const;
+
+ virtual void getCenterGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ ossim_uint32 level,
+ const osg::Vec3d& latLon)const;
+
+ virtual void createGridPoints(std::vector<ossimPlanetGridUtility::GridPoint>& points,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ ossim_uint32 rows,
+ ossim_uint32 cols)const;
+
+
+ virtual void getLatLon(osg::Vec3d& latLon,
+ const ossimPlanetGridUtility::GridPoint& gridPoint)const=0;
+ virtual void getGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ const osg::Vec3d& latLon)const=0;
+ virtual void getLatLonCorners(osg::Vec3d& ul,
+ osg::Vec3d& ur,
+ osg::Vec3d& lr,
+ osg::Vec3d& ll,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const;
+ virtual void getCenterLatLon(osg::Vec3d& center,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const;
+ virtual void getLatLonBounds(double& minLat,
+ double& minLon,
+ double& maxLat,
+ double& maxLon,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+
+ virtual void getNumberOfTilesWideHigh(ossim_uint64 &wide,
+ ossim_uint64 &high,
+ ossim_uint32 level)const;
+
+ virtual ossim_uint64 getNumberOfTiles(ossim_uint32 level)const;
+ virtual ossim_uint64 getTotalNumberOfTiles(ossim_uint32 level)const;
+
+ virtual ossim_uint64 getId(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+
+ ossim_uint32 getTileWidth()const;
+ ossim_uint32 getTileHeight()const;
+
+ void setTileWidthHeight(ossim_uint32 tileWidth,
+ ossim_uint32 tileHeight);
+
+
+protected:
+ ossim_uint32 theTileWidth;
+ ossim_uint32 theTileHeight;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIconGeom.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIconGeom.h
new file mode 100644
index 0000000..5ac8ee4
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIconGeom.h
@@ -0,0 +1,44 @@
+#ifndef ossimPlanetIconGeom_HEADER
+#define ossimPlanetIconGeom_HEADER
+#include <osg/Geometry>
+#include <osg/Vec3d>
+#include <osg/Texture2D>
+#include <ossim/base/ossimConstants.h>
+
+class ossimPlanetIconGeom : public osg::Geometry
+{
+public:
+ /**
+ * We will setup a unit geometry for the icon.
+ */
+ ossimPlanetIconGeom( const osg::Vec3d& corner=osg::Vec3d(-.5,
+ 0.0,
+ -.5),
+ const osg::Vec3d& width=osg::Vec3d(1.0,0.0,0.0),
+ const osg::Vec3d& height=osg::Vec3d(0.0,0.0,1.0));
+ void setTexture(osg::ref_ptr<osg::Image> img);
+ void setTexture(osg::ref_ptr<osg::Texture2D> texture);
+ void resetToUnitGeometry();
+ void setGeometry(const osg::Vec3d& corner,
+ const osg::Vec3d& width,
+ const osg::Vec3d& height);
+ void setTextureCoordinatesGivenPixels(int originX,
+ int originY,
+ int pixelWidth,
+ int pixelHeight);
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
+ ossim_uint32 width()const;
+ ossim_uint32 height()const;
+ osg::ref_ptr<osg::Texture2D> texture();
+ const osg::ref_ptr<osg::Texture2D> texture()const;
+protected:
+ void setupGeom(const osg::Vec3d& corner,
+ const osg::Vec3d& width,
+ const osg::Vec3d& height);
+ osg::ref_ptr<osg::Texture2D> theTexture;
+ mutable osg::ref_ptr<osg::Vec4dArray> theColorArray;
+ float theAlpha;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetId.h b/ossimPlanet/include/ossimPlanet/ossimPlanetId.h
new file mode 100644
index 0000000..26defcd
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetId.h
@@ -0,0 +1,79 @@
+#ifndef ossimPlanetId_HEADER
+#define ossimPlanetId_HEADER
+#include <ossim/base/ossimConstants.h>
+#include "ossimPlanetExport.h"
+
+class OSSIMPLANET_DLL ossimPlanetId
+{
+public:
+ ossimPlanetId(ossim_int64 value = theInvalidId)
+ :theId(value)
+ {
+ }
+ ossim_int64 id()const
+ {
+ return theId;
+ }
+ ossimPlanetId& operator ++()
+ {
+ ++theId;
+ return *this;
+ }
+ ossimPlanetId operator ++(int)
+ {
+ ossimPlanetId id(theId);
+ ++theId;
+ return id;
+ }
+ bool operator()()const
+ {
+ return (theId != theInvalidId);
+ }
+ bool operator <(const ossimPlanetId& id)const
+ {
+ return (theId < id.theId);
+ }
+ bool operator <(ossim_int64 id)const
+ {
+ return (theId < id);
+ }
+ bool operator >(const ossimPlanetId& id)const
+ {
+ return (theId > id.theId);
+ }
+ bool operator >(ossim_int64 id)const
+ {
+ return (theId > id);
+ }
+ bool operator <=(const ossimPlanetId& id)const
+ {
+ return (theId <= id.theId);
+ }
+ bool operator <=(ossim_int64 id)const
+ {
+ return (theId <= id);
+ }
+ bool operator >=(const ossimPlanetId& id)const
+ {
+ return (theId >= id.theId);
+ }
+ bool operator >=(ossim_int64 id)const
+ {
+ return (theId >= id);
+ }
+ bool operator ==(const ossimPlanetId& id)const
+ {
+ return (theId == id.theId);
+ }
+ bool operator ==(ossim_int64 id)const
+ {
+ return (theId == id);
+ }
+ static ossim_int64 invalidId();
+protected:
+ ossim_int64 theId;
+
+ static ossim_int64 theInvalidId;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIdManager.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIdManager.h
new file mode 100644
index 0000000..16cae52
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIdManager.h
@@ -0,0 +1,15 @@
+#ifndef ossimPlanetIdManager_HEADER
+#define ossimPlanetIdManager_HEADER
+#include "ossimPlanetId.h"
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include "ossimPlanetExport.h"
+class OSSIMPLANET_DLL ossimPlanetIdManager
+{
+public:
+ static ossimPlanetId nextId();
+
+protected:
+ static ossimPlanetId theCurrentId;
+ static ossimPlanetReentrantMutex theMutex;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIdolBridge.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIdolBridge.h
new file mode 100644
index 0000000..5d681f3
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIdolBridge.h
@@ -0,0 +1,105 @@
+// Written by Patrick Melody @ NRL
+
+#ifndef ossimPlanetIdolBridge_HEADER
+#define ossimPlanetIdolBridge_HEADER
+
+#include <map>
+#include <osg/Group>
+#include "ossimPlanet/ossimPlanetActionReceiver.h"
+#include "ossimPlanet/ossimPlanetIdolLayer.h"
+
+class ossimPlanetIdolBridge : public ossimPlanetActionReceiver {
+public:
+ ossimPlanetIdolBridge() :
+ layerGroup_(new osg::Group)
+ {
+ setPathnameAndRegister(":idolbridge");
+ }
+
+ ~ossimPlanetIdolBridge()
+ {
+ for (std::map<std::string, ossimPlanetIdolLayer*>::iterator i = layers_.begin(); i != layers_.end(); i++) {
+ layerGroup_->removeChild(i->second->layerRoot());
+ delete i->second;
+ }
+ }
+
+ void execute(const ossimPlanetAction &a)
+ {
+ if (a.command() == "gotolatlonelev") {
+ // this action updates our current position to idol.
+ // we do nothing. this action is being broadcast so all
+ // idol data servers see it, and it is intended for them.
+
+ } else if (a.command() == "movechild") {
+ if (a.argCount() == 5) {
+ std::map<std::string, ossimPlanetIdolLayer*>::iterator i = layers_.find(a.arg(1));
+ if (i != layers_.end())
+ i->second->moveChild(a);
+ else
+ a.printError("no such layer");
+ } else
+ a.printError("bad arg count, need layername,childname,lat,lon,elev");
+
+ } else if (a.command() == "addchild") {
+ if (a.argCount() == 6) {
+ std::map<std::string, ossimPlanetIdolLayer*>::iterator i = layers_.find(a.arg(1));
+ if (i != layers_.end())
+ i->second->addChild(a);
+ else
+ a.printError("no such layer");
+ } else
+ a.printError("bad arg count, need layername,childname,lat,lon,elev,modeldata");
+
+ } else if (a.command() == "removechild") {
+ if (a.argCount() == 2) {
+ std::map<std::string, ossimPlanetIdolLayer*>::iterator i = layers_.find(a.arg(1));
+ if (i != layers_.end())
+ i->second->removeChild(a);
+ else
+ a.printError("no such layer");
+ } else
+ a.printError("bad arg count, need layername,childname");
+
+ } else if (a.command() == "createlayer") {
+ if (a.argCount() == 1) {
+ std::map<std::string, ossimPlanetIdolLayer*>::iterator i = layers_.find(a.arg(1));
+ if (i == layers_.end()) {
+ layers_[a.arg(1)] = new ossimPlanetIdolLayer(a.arg(1));
+ layerGroup_->addChild(layers_[a.arg(1)]->layerRoot());
+ } else
+ a.printError("layer already exists");
+ } else
+ a.printError("bad arg count");
+
+ } else if (a.command() == "deletelayer") {
+ if (a.argCount() == 1) {
+ std::map<std::string, ossimPlanetIdolLayer*>::iterator i = layers_.find(a.arg(1));
+ if (i != layers_.end()) {
+ layerGroup_->removeChild(i->second->layerRoot());
+ delete i->second;
+ layers_.erase(i);
+ } else
+ a.printError("no such layer");
+ } else
+ a.printError("bad arg count");
+
+ } else
+ a.printError("bad command");
+ }
+
+ osg::ref_ptr<osg::Group> layerGroup() const
+ // this group is attached to the scenegraph by class ossimPlanet. idol layer groups live under it.
+ { return layerGroup_; }
+
+protected:
+ osg::ref_ptr<osg::Group> layerGroup_;
+ // this group is attached to the scenegraph by class ossimPlanet. idol layer groups live under it.
+
+ std::map<std::string, ossimPlanetIdolLayer*> layers_;
+ // all our current layers indexed by layer name
+
+};
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIdolLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIdolLayer.h
new file mode 100644
index 0000000..db2cb32
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIdolLayer.h
@@ -0,0 +1,140 @@
+// a data layer loaded by idol, controlled by an ossimPlanetIdolBridge
+
+// Written by Patrick Melody @ NRL
+
+#ifndef ossimPlanetIdolLayer_HEADER
+#define ossimPlanetIdolLayer_HEADER
+
+#include <vector>
+#include <map>
+#include <string>
+#include <osg/MatrixTransform>
+#include <osg/Group>
+#include <osg/Geode>
+#include <osgText/Text>
+#include <osgDB/ReadFile>
+#include "ossimPlanet/ossimPlanetAction.h"
+#include "ossimPlanet/mkUtils.h"
+
+class ossimPlanetIdolLayer {
+public:
+ ossimPlanetIdolLayer(const std::string& name) :
+ name_(name),
+ layerRoot_(new osg::Group)
+ { }
+
+ ~ossimPlanetIdolLayer()
+ {
+ for (std::map<std::string, osg::MatrixTransform*>::iterator i = children_.begin(); i != children_.end(); i++)
+ i->second->unref();
+ }
+
+ void addChild(const ossimPlanetAction &a)
+ // create and add a child; args are layername childname lat lon elev modeldescription
+ {
+ if (children_.find(a.arg(2)) == children_.end()) {
+ osg::Node* model = createModelFromDescription(a.arg(6));
+ if (model != NULL) {
+ osg::MatrixTransform* xform = new osg::MatrixTransform;
+ xform->ref();
+ setTransform(xform, mkUtils::asDouble(a.arg(3)), mkUtils::asDouble(a.arg(4)), mkUtils::asDouble(a.arg(5)));
+ xform->addChild(model);
+ layerRoot_->addChild(xform);
+ children_[a.arg(2)] = xform;
+ } else
+ a.printError("could not create model from model description");
+ } else
+ a.printError("already have a child with that name");
+ }
+
+ void moveChild(const ossimPlanetAction &a)
+ // move a child; args are layername childname lat lon elev
+ {
+ std::map<std::string, osg::MatrixTransform*>::iterator i = children_.find(a.arg(2));
+ if (i != children_.end())
+ setTransform(i->second, mkUtils::asDouble(a.arg(3)), mkUtils::asDouble(a.arg(4)), mkUtils::asDouble(a.arg(5)));
+ else
+ a.printError("no such child");
+ }
+
+ void removeChild(const ossimPlanetAction &a)
+ // remove a child
+ {
+ std::map<std::string, osg::MatrixTransform*>::iterator i = children_.find(a.arg(2));
+ if (i != children_.end()) {
+ layerRoot_->removeChild(i->second);
+ i->second->unref();
+ children_.erase(i);
+ } else
+ a.printError("no such child");
+ }
+
+ const std::string& name() const
+ // name of this layer
+ { return name_; }
+
+ osg::Group* layerRoot() const
+ // root of this layer's scene subgraph
+ { return layerRoot_.get(); }
+
+protected:
+ std::string name_;
+ // layer name
+
+ osg::ref_ptr<osg::Group> layerRoot_;
+ // root of this layer's scene subgraph
+
+ std::map<std::string, osg::MatrixTransform*> children_;
+ // collection of current children indexed by childname
+
+ osg::Node* createModelFromDescription(const std::string& modelDescription) const
+ // create model
+ // modeldescription := (text labeltext r g b a scale) | (model filename scale)
+ {
+ osg::Node* result = NULL;
+
+ std::vector<std::string> tokens;
+ bool unbalancedBraces;
+ mkUtils::lexBraceQuotedTokens(modelDescription, 0, " \t", &tokens, &unbalancedBraces);
+
+ if (!unbalancedBraces && tokens.size() > 0) {
+ if (tokens[0] == "text" && tokens.size() == 7) {
+ osgText::Text* t = new osgText::Text;
+ t->setFont();
+ t->setCharacterSize(6.0f*mkUtils::asDouble(tokens[6]));
+ t->setColor(osg::Vec4f(mkUtils::asDouble(tokens[2]), mkUtils::asDouble(tokens[3]), mkUtils::asDouble(tokens[4]), mkUtils::asDouble(tokens[5])));
+ t->setAlignment(osgText::Text::CENTER_CENTER);
+ t->setText(tokens[1]);
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(t);
+ result = geode;
+
+ } else if (tokens[0] == "model" && tokens.size() == 3) {
+ osg::Node* model = osgDB::readNodeFile(tokens[1].c_str());
+ if (model != NULL) {
+ double scale = mkUtils::asDouble(tokens[2]);
+ osg::MatrixTransform* scaleNode = new osg::MatrixTransform(osg::Matrixf::scale(scale,scale,scale));
+ scaleNode->addChild(model);
+ result = scaleNode;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ void setTransform(osg::MatrixTransform* transform, double lat, double lon, double elev) const
+ // set transform to place geometry at lat,lon,elev
+ {
+ const osg::Vec3d zAxis(0.0, 0.0, 1.0);
+
+ double planetRadius = 6378137.0; // XXX should really compute current planet's radius at lat/lon
+ osg::Vec3d v = mkUtils::modsphere2xyz(1.0 + elev/planetRadius, osg::DegreesToRadians(lon), osg::DegreesToRadians(lat));
+
+ transform->setMatrix(osg::Matrixd::rotate(osg::DegreesToRadians(lon + 90.0), zAxis));
+ transform->postMult(osg::Matrixd::rotate(zAxis, v));
+ transform->postMult(osg::Matrixd::translate(v));
+ }
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetImage.h b/ossimPlanet/include/ossimPlanet/ossimPlanetImage.h
new file mode 100644
index 0000000..9e57fca
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetImage.h
@@ -0,0 +1,186 @@
+#ifndef ossimPlanetImage_HEADER
+#define ossimPlanetImage_HEADER
+#include "ossimPlanetExport.h"
+#include <ossim/base/ossimConstants.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <osg/Image>
+#include <osg/Vec2>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetTerrainTileId.h>
+
+class OSSIMPLANET_DLL ossimPlanetImage :public osg::Image
+{
+public:
+ enum ossimPlanetImageStateType
+ {
+ ossimPlanetImageStateType_NONE = 0,
+ ossimPlanetImageStateType_LOADED = 1,
+ ossimPlanetImageStateType_NEEDS_LOADING = 2
+ };
+ enum ossimPlanetImagePixelStatus
+ {
+ ossimPlanetImagePixelStatus_EMPTY = 0,
+ ossimPlanetImagePixelStatus_FULL = 1,
+ ossimPlanetImagePixelStatus_PARTIAL = 2
+ };
+ virtual osg::Object* cloneType() const
+ {
+ return new ossimPlanetImage();
+ }
+ virtual osg::Object* clone(const osg::CopyOp& copyop) const
+ {
+ return new ossimPlanetImage(*this,copyop);
+ }
+ virtual const char* className() const
+ {
+ return "ossimPlanetImage";
+ }
+ ossimPlanetImage();
+ ossimPlanetImage(const osg::Image& image);
+ ossimPlanetImage(const ossimPlanetTerrainTileId& id);
+ ossimPlanetImage(const ossimPlanetImage& image,
+ const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ virtual ~ossimPlanetImage();
+ void stripPadding();
+ int getNumberOfComponents()const;
+ int getHeight()const;
+ int getWidth()const;
+
+ ossimPlanetImageStateType getState()const;
+
+ void setId(const ossimPlanetTerrainTileId& id);
+ const ossimPlanetTerrainTileId& tileId()const;
+ void setState(ossimPlanetImageStateType stateType);
+ void setPixelStatus();
+ void setPixelStatus(ossimPlanetImagePixelStatus pixelStatus);
+ ossimPlanetImagePixelStatus getPixelStatus()const;
+ ossimRefPtr<ossimImageData> toOssimImage()const;
+ void fromOssimImage(ossimRefPtr<ossimImageData> data,
+ bool reassignNullFlag = true,
+ double nullValue = 0.0);
+ void fromOssimImageNoAlpha(ossimRefPtr<ossimImageData> data,
+ bool reassignNullFlag = true,
+ double nullValue = 0.0);
+ OpenThreads::Mutex& mutex()const;
+
+ bool hasMinMax()const
+ {
+ return ((theMinValue.size()!=0)&&
+ (theMaxValue.size()!=0));
+ }
+ void setMinMax(double minValue,
+ double maxValue)
+ {
+ theMinValue.resize(1);
+ theMaxValue.resize(1);
+
+ theMinValue[0] = minValue;
+ theMaxValue[0] = maxValue;
+ }
+ void setMin(ossim_uint32 idx,
+ double value)
+ {
+ if(idx < theMinValue.size())
+ {
+ theMinValue[idx] = value;
+ }
+ }
+ void setMax(ossim_uint32 idx,
+ double value)
+ {
+ if(idx < theMaxValue.size())
+ {
+ theMaxValue[idx] = value;
+ }
+ }
+ void setMinMax(const std::vector<double>& minValue,
+ const std::vector<double>& maxValue)
+ {
+ theMinValue = minValue;
+ theMaxValue = maxValue;
+ }
+ const std::vector<double>& minValue()const
+ {
+ return theMinValue;
+ }
+ const std::vector<double>& maxValue()const
+ {
+ return theMaxValue;
+ }
+ static osg::Image* readNewOsgImage(const ossimFilename& src,
+ bool flipVerticalFlag = true,
+ bool insertAlphaFlag = true);
+ static osg::Image* readNewOsgImageNoAlpha(const ossimFilename& src,
+ bool flipVerticalFlag = true);
+ ossimPlanetImage* scaleImagePowerOf2()const;
+
+ void copyTo(ossim_uint32 x, ossim_uint32 y, ossimPlanetImage* destination)const;
+
+ /**
+ * We will only support RGBA or RGB, or single band elevation in 32 bit float
+ */
+ void copySubImageAndInsertPointsPowerOf2(int x, // starting x
+ int y, // starting y
+ ossim_uint32 lengthx, // length x
+ ossim_uint32 lengthy, // length y
+ ossimPlanetImage* source);
+ virtual ossim_uint64 sizeInBytes()const;
+ virtual osg::Vec2 deltas(ossim_int32 x,
+ ossim_int32 y)const;
+
+ ossim_int32 widthWithoutPadding()const
+ {
+ return _s-(thePadding*2);
+ }
+ ossim_int32 heightWithoutPadding()const
+ {
+ return _t-(thePadding*2);
+ }
+ ossim_int32 width()const{return _s;}
+ ossim_int32 height()const{return _t;}
+
+ ossim_int32 padding()const
+ {
+ return thePadding;
+ }
+ void setPadding(ossim_int32 value)
+ {
+ thePadding = value;
+ }
+ ossim_float32 elevationValue(ossim_int32 x, ossim_int32 y)const
+ {
+ return reinterpret_cast<const ossim_float32*>(_data)[_s*y+x];
+ }
+ ossim_float32 elevationValueNoPaddingOffset(ossim_int32 x, ossim_int32 y)const
+ {
+ return reinterpret_cast<const ossim_float32*>(_data)[_s*(y+thePadding)+(x+thePadding)];
+ }
+ void applyBrightnessContrast(ossim_float32 brightness, ossim_float32 contrast);
+
+protected:
+ template <class T>
+ void copySubImageAndInsertPointsPowerOf2(T dummy, // for casting to proper buffer type
+ int x,
+ int y, // starting y
+ ossim_uint32 lengthx, // length x
+ ossim_uint32 lengthy, // length y
+ ossimPlanetImage* source); //
+ template <class T>
+ ossimPlanetImage* scaleImagePowerOf2(T dummy)const;
+
+ template <class T>
+ void copyTo(T dummy, ossim_uint32 x, ossim_uint32 y, ossimPlanetImage* destination)const;
+
+ mutable ossimPlanetImageStateType theState;
+ ossimPlanetTerrainTileId theTileId;
+ ossimPlanetImagePixelStatus thePixelStatus;
+ mutable ossimPlanetReentrantMutex theMutex;
+ std::vector<double> theMinValue;
+ std::vector<double> theMaxValue;
+
+ ossim_int32 thePadding;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetInputDevice.h b/ossimPlanet/include/ossimPlanet/ossimPlanetInputDevice.h
new file mode 100644
index 0000000..9d99efa
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetInputDevice.h
@@ -0,0 +1,20 @@
+#ifndef ossimPlanetInputDevice_HEADER
+#define ossimPlanetInputDevice_HEADER
+
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Referenced>
+// device driver interface for user input devices
+
+class OSSIMPLANET_DLL ossimPlanetInputDevice :public osg::Referenced
+{
+public:
+ ossimPlanetInputDevice() {}
+ virtual ~ossimPlanetInputDevice() {}
+
+ virtual void processInput() = 0;
+ // update interaction valuators and execute actions
+
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetInteractionController.h b/ossimPlanet/include/ossimPlanet/ossimPlanetInteractionController.h
new file mode 100644
index 0000000..0b5e49b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetInteractionController.h
@@ -0,0 +1,154 @@
+#ifndef ossimPlanetInteractionController_HEADER
+#define ossimPlanetInteractionController_HEADER
+
+// Control mapping configuration, notify sim of user input.
+// Events are discrete inputs, eg button presses, bound to actions.
+// Events beginning with a '-' are reserved for commandline arguments.
+// Device valuators are continuous inputs, eg mouse position, tied
+// to interaction valuators.
+
+#include <assert.h>
+#include <iostream>
+#include <map>
+#include <vector>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/ossimPlanetInputDevice.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ScopedLock>
+#include <osg/ref_ptr>
+
+class OSSIMPLANET_DLL ossimPlanetInteractionController : public ossimPlanetActionReceiver
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetInputDevice> > DeviceList;
+
+ // singleton routines
+ static ossimPlanetInteractionController* instance();
+ // pointer to the lazy initialized InteractionController singleton
+ // assert(instance() != NULL)
+
+ static void shutdown();
+ // clean up the singleton
+
+ // input management
+ void registerDevice(ossimPlanetInputDevice* d);
+ // add an input device to the list of devices we watch
+ // assert(d != NULL)
+
+ void unregisterDevice(ossimPlanetInputDevice* d);
+ // remove an input device from the list of devices we watch
+ // assert(d != NULL)
+
+ void processPendingInputs();
+ // generate all actions and update all variables required
+ // by any user input to a registered device that occured
+ // since last call.
+
+ void defineInteractionValuator(const std::string& name, double minValue, double maxValue);
+ // define an interaction valuator
+ // assert(!name.empty());
+ // assert(!ossim::isnan(minValue));
+ // assert(!ossim::isnan(maxValue));
+
+ float interactionValuatorValue(const std::string& interactionValuator) const;
+ // value of an interaction valuator, or NAN if undefined valuator
+
+ // user control configuration
+ void bind(const std::string& event, const ossimPlanetAction& a);
+ // bind an event to an action
+ // assert(!event.empty()) // reserve empty event name for noops
+
+ void unbind(const std::string& event);
+ // unbind event
+
+ void unbindAll();
+ // unbind all events
+
+ void tie(const std::string& valuatorList);
+ // given a brace quoted token list, treat the first token as a device valuator name,
+ // and the rest of the tokens as virtual interaction valuator names. untie the
+ // device valuator from any previous ties and then tie it to all the listed
+ // interaction valuators that are currently defined.
+
+ void untie(const std::string& deviceValuator);
+ // untie a device valuator from all its virtual interaction valuators
+
+ void untieAll();
+ // untie all device valuators from all their virtual interaction valuators
+
+ void writeConfiguration(std::ostream& stream) const;
+ // output an action script that will restore the current bindings/ties
+
+ // routines called by InputDevice objects
+ void executeBoundAction(const std::string& event);
+ // execute the action bound to event, no op if no binding
+
+ void updateInteractionValuators(const std::string& deviceValuator, float normalizedValue);
+ // update value of all interaction valuators tied to deviceValuator
+ // assert(mkUtils::inInterval(normalizedValue, 0.0f, 1.0f))
+
+ // ActionReceiver routines
+ void execute(const ossimPlanetAction& a);
+ // execute the given action
+
+protected:
+ ossimPlanetInteractionController();
+ ossimPlanetInteractionController(const ossimPlanetInteractionController& src):ossimPlanetActionReceiver(src) {}
+ ~ossimPlanetInteractionController();
+ ossimPlanetInteractionController& operator=(ossimPlanetInteractionController& ) {assert(false); return *this;}
+
+ void xmlExecute(const ossimPlanetXmlAction& a);
+ void destinationCommandExecute(const ossimPlanetDestinationCommandAction& a);
+ static ossimPlanetInteractionController* instance_;
+ // our singleton
+
+ DeviceList deviceList_;
+ // registered input devices
+
+ mutable ossimPlanetReentrantMutex theBoundActionsMutex;
+ std::map<std::string, osg::ref_ptr<ossimPlanetAction> > boundActions_;
+ // current event to action bindings
+
+ class ossimPlanetInteractionValuatorData
+ {
+ public:
+ double min;
+ double maxMinusMin;
+ double value;
+ ossimPlanetInteractionValuatorData() : min(0.0), maxMinusMin(1.0), value(0.0) {}
+ ossimPlanetInteractionValuatorData(float minVal, float maxVal) : min(minVal), maxMinusMin(maxVal-minVal), value(minVal) {}
+ };
+ // valuator data tuple
+
+ std::map<std::string, ossimPlanetInteractionValuatorData> valuators_;
+ // all defined interaction valuators
+
+ std::map<std::string, std::vector<std::string> > deviceTies_;
+ // device valuators and the interaction valuators they're tied to
+};
+
+inline ossimPlanetInteractionController* ossimPlanetInteractionController::instance()
+{
+ if (ossimPlanetInteractionController::instance_ == 0)
+ {
+ ossimPlanetInteractionController::instance_ = new ossimPlanetInteractionController();
+ }
+ assert(ossimPlanetInteractionController::instance_ != NULL);
+ return ossimPlanetInteractionController::instance_;
+}
+
+inline void ossimPlanetInteractionController::shutdown()
+{
+ if(ossimPlanetInteractionController::instance_)
+ {
+ delete ossimPlanetInteractionController::instance_;
+ ossimPlanetInteractionController::instance_ = 0;
+ }
+}
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIntersectUserData.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIntersectUserData.h
new file mode 100644
index 0000000..8d3142d
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIntersectUserData.h
@@ -0,0 +1,27 @@
+#ifndef ossimPlanetIntersectUserData_HEADER
+#define ossimPlanetIntersectUserData_HEADER
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetIntersectUserData : public osg::Referenced
+{
+public:
+ ossimPlanetIntersectUserData(int maxLevel=9999999)
+ :theMaxLevelToIntersect(maxLevel)
+ {
+ }
+
+ void setMaxLevelToIntersect(int maxLevel)
+ {
+ theMaxLevelToIntersect = maxLevel;
+ }
+ int getMaxLevelToIntersect()const
+ {
+ return theMaxLevelToIntersect;
+ }
+protected:
+ virtual ~ossimPlanetIntersectUserData(){}
+
+ int theMaxLevelToIntersect;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIo.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIo.h
new file mode 100644
index 0000000..62f285f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIo.h
@@ -0,0 +1,156 @@
+#ifndef ossimPlanetIo_HEADER
+#define ossimPlanetIo_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetMessage.h>
+#include <vector>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ScopedLock>
+
+class OSSIMPLANET_DLL ossimPlanetIo : public osg::Referenced
+{
+public:
+ typedef char BufferType;
+ typedef std::vector<char> ByteBufferType;
+ enum IoResultType
+ {
+ IO_SUCCESS = 0,
+ IO_NO_DATA = 1,
+ IO_FAIL = 2
+ };
+ ossimPlanetIo(const ossimString& name="",
+ char terminator='\0')
+ :theName(name),
+ theTerminator(terminator),
+ theFinishedFlag(false),
+ theEnableFlag(true)
+ {
+ }
+
+ virtual ~ossimPlanetIo()
+ {
+ }
+
+ virtual void performIo()=0;
+
+ /**
+ * This is a general interface into Io for reading data.
+ *
+ * @param buffer is a fixed size buffer that we read data and put into it.
+ * @param bufferSize Size of the buffer.
+ * @result The amount of bytes read into the buffer.
+ */
+ virtual ossim_uint32 read(char* buffer, ossim_uint32 bufferSize, ossimPlanetIo::IoResultType& ioResult)=0;
+
+ /**
+ * This is a general interface into Io for writing data.
+ *
+ * @param buffer is a buffer that we either read data and put into it.
+ * @param bufferSize Size of the buffer.
+ * @param ioResult Specifies if the IO was succesful or if no data was present or if it failed. On failure derived IO
+ * can deterimine the action they want to take.
+ * @result The amount of bytes writen into the buffer.
+ */
+ virtual ossim_uint32 write(const char* buffer, ossim_uint32 bufferSize, ossimPlanetIo::IoResultType& ioResult)=0;
+
+ virtual bool pushMessage(osg::ref_ptr<ossimPlanetMessage> /*message*/, bool /*forcePushFlag*/)
+ {
+ return false;
+ }
+ virtual osg::ref_ptr<ossimPlanetMessage> popMessage()
+ {
+ return 0;
+ }
+ virtual void setConnectionHeader(osg::ref_ptr<ossimPlanetMessage> value)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ theConnectionHeader = value;
+ }
+ void setFinishedFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ theFinishedFlag = flag;
+ }
+ bool finishedFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ return theFinishedFlag;
+ }
+ const ossimString& name()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ return theName;
+ }
+ void setName(const ossimString& name)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ theName = name;
+ }
+ virtual void searchName(ossimString& searchNameResult)const
+ {
+ // by default we will return the name. Derived classes should return
+ // a full ID name. For example, sockets will return <name>:<port>
+ searchNameResult = name();
+ }
+ char terminator()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ return theTerminator;
+ }
+ void setTerminator(char terminator)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ theTerminator = terminator;
+ }
+ virtual void setEnableFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ theEnableFlag = flag;
+ }
+ bool enableFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ return theEnableFlag;
+ }
+ void setIoDirection(ossimPlanetIoDirection direction)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ theIoDirection = direction;
+ }
+ ossimPlanetIoDirection ioDirection()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ return theIoDirection;
+ }
+ virtual void pushConnectionHeader()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetIoPropertyMutex);
+ if(theConnectionHeader.valid())
+ {
+ if(theConnectionHeader->dataSize() > 0)
+ {
+ pushMessage(theConnectionHeader, true);
+ }
+ }
+ }
+ virtual void closeIo()=0;
+ virtual bool openIo()=0;
+
+private:
+ ossimString theName;
+ char theTerminator;
+ bool theFinishedFlag;
+ bool theEnableFlag;
+ ossimPlanetIoDirection theIoDirection;
+ osg::ref_ptr<ossimPlanetMessage> theConnectionHeader;
+ mutable ossimPlanetReentrantMutex thePlanetIoPropertyMutex;
+protected:
+ mutable ossimPlanetReentrantMutex theIoMutex;
+
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIoMessageHandler.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIoMessageHandler.h
new file mode 100644
index 0000000..78c0f0f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIoMessageHandler.h
@@ -0,0 +1,40 @@
+#ifndef ossimPlanetIoMessageHandler_HEADER
+#define ossimPlanetIoMessageHandler_HEADER
+#include <ossim/base/ossimString.h>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <vector>
+#include <ossimPlanet/ossimPlanetMessage.h>
+
+class ossimPlanetIoMessageHandler : public osg::Referenced
+{
+public:
+ ossimPlanetIoMessageHandler()
+ :theName(""),
+ theEnableFlag(true)
+ {}
+ virtual bool handleMessage(osg::ref_ptr<ossimPlanetMessage> message)=0;
+ void setEnableFlag(bool flag)
+ {
+ theEnableFlag = flag;
+ }
+ bool enableFlag()const
+ {
+ return theEnableFlag;
+ }
+
+ void setName(const ossimString& name)
+ {
+ theName = name;
+ }
+ const ossimString& name()const
+ {
+ return theName;
+ }
+protected:
+ ossimString theName;
+ bool theEnableFlag;
+};
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIoRoutableMessageHandler.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIoRoutableMessageHandler.h
new file mode 100644
index 0000000..f220f34
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIoRoutableMessageHandler.h
@@ -0,0 +1,15 @@
+#ifndef ossimPlanetIoRoutableMessageHandler_HEADER
+#define ossimPlanetIoRoutableMessageHandler_HEADER
+#include <ossimPlanet/ossimPlanetIoMessageHandler.h>
+
+class ossimPlanetIoRoutableMessageHandler : public ossimPlanetIoMessageHandler
+{
+public:
+ ossimPlanetIoRoutableMessageHandler()
+ {
+ theName = "Routable Message Handler";
+ }
+ virtual bool handleMessage(osg::ref_ptr<ossimPlanetMessage> message);
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIoSocket.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIoSocket.h
new file mode 100644
index 0000000..b87ddd2
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIoSocket.h
@@ -0,0 +1,125 @@
+#ifndef ossimPlanetIoSocket_HEADER
+#define ossimPlanetIoSocket_HEADER
+#include <ossimPlanet/ossimPlanetIo.h>
+#include <ossimPlanet/netSocket.h>
+#include <queue>
+#include <deque>
+#include <osg/Timer>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <OpenThreads/Mutex>
+
+class OSSIMPLANET_DLL ossimPlanetIoSocket : public ossimPlanetIo
+{
+public:
+ typedef std::deque<osg::ref_ptr<ossimPlanetMessage> > OutQueueType;
+ ossimPlanetIoSocket();
+ virtual ~ossimPlanetIoSocket();
+
+ void setHandle(int handle);
+ void setSocketInfo(const ossimString& host,
+ int port,
+ const ossimString& ioType);
+ virtual void searchName(ossimString& searchNameResult)const;
+ bool setSocket(const ossimString& host,
+ int port,
+ const ossimString& ioType);
+ int handle()
+ {
+ if(theSocket) return theSocket->getHandle();
+ return -1;
+ }
+ virtual ossim_uint32 read(char* buffer, ossim_uint32 bufferSize, ossimPlanetIo::IoResultType& ioResult);
+ virtual ossim_uint32 write(const char* buffer, ossim_uint32 bufferSize, ossimPlanetIo::IoResultType& ioResult);
+
+ bool nonblock();
+ bool setBlockingFlag(bool flag);
+ virtual void setEnableFlag(bool flag);
+ const ossimString& host()const;
+ int port()const;
+ const ossimString& ioType()const;
+ virtual void performIo();
+ virtual bool pushMessage(osg::ref_ptr<ossimPlanetMessage> message, bool forcePushFlag);
+ virtual osg::ref_ptr<ossimPlanetMessage> popMessage();
+ virtual void clearAllBuffers();
+ //void setAutoCloseOnPeerShutdownFlag(bool flag);
+ //bool autoCloseOnPeerShutdownFlag()const;
+ void setAutoReconnectFlag(bool flag);
+ bool autoReconnectFlag()const;
+ void setAutoReconnectInterval(ossim_uint32 milliseconds);
+ ossim_uint32 autoReconnectInterval()const;
+ void setMaxOutputBacklogInBytes(ossim_uint32 bytes);
+ ossim_uint32 maxOutputBacklogInBytes()const;
+ virtual void closeIo();
+ virtual bool openIo();
+
+ void setMaxBytesToSendPerIo(ossim_uint32 byte);
+ ossim_uint32 maxBytesToSendPerIo()const;
+protected:
+ bool makeClientSocket();
+ bool protectedSetSocket(const ossimString& host,
+ int port,
+ const ossimString& ioType);
+ void addToOutputBufferIfNeeded();
+
+ netSocket* theSocket;
+ ossimString theHost;
+ int thePort;
+ ossimString theIoType; // can be udp or tcp
+ bool theStreamingFlag;
+ ossimPlanetIo::ByteBufferType theTempBuffer;
+ ossimPlanetIo::ByteBufferType theInBuffer;
+
+ // The In queue is where incoming messages are stored and will be popped and handled in the thread
+ //
+ ossimPlanetReentrantMutex theInQueueMutex;
+ std::queue<osg::ref_ptr<ossimPlanetMessage> > theInQueue;
+
+ // The out queue will hold all outgoing messages
+ ossimPlanetReentrantMutex theOutQueueMutex;
+ OutQueueType theOutQueue;
+ ossimPlanetReentrantMutex theOutBufferMutex;
+ std::vector<char> theOutBuffer;
+
+ /**
+ * If this flag is true then it will auto shutdown the client socket if a server shutdown is
+ * detected. So if a client socket is communicating and it gets a bad send or receive that indicates
+ * a server shutdown it will set its finished flag if this flag is true.
+ */
+ //bool theAutoCloseOnPeerShutdownFlag;
+
+ /**
+ * This specifies if the client socket is disconnected it should try to reconnect
+ */
+ bool theAutoReconnectFlag;
+
+ /**
+ * if the AutoReconnectFlag is true then it will try to reconnect at the specified
+ * interval. The interval is in Milleseconds. So if you want a reconnect attempt
+ * to happen approximately every second then the value should be set to 1000. This
+ * is the default value.
+ */
+ ossim_uint32 theAutoReconnectInterval; // specified in milliseconds
+
+ mutable ossimPlanetReentrantMutex theMaxBytesToSendPerIoMutex;
+ ossim_uint32 theMaxBytesToSendPerIo;
+
+ ossim_uint32 theMaxOutgoingBacklogInBytes;
+
+ ossim_int32 theTotalBytesToSend;
+ /**
+ * Used in the reconnect interval This is reset to 0 for identification that an initial
+ * tick needs to be set. once set the delta milliseconds is used to determine
+ * when to do another reconnect.
+ */
+ osg::Timer_t theLastTick;
+
+ ossimPlanetReentrantMutex theSocketMutex;
+
+ bool theFirstReadFlag;
+
+ /**
+ * Bytes to auto send on connection
+ */
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIoSocketServerChannel.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIoSocketServerChannel.h
new file mode 100644
index 0000000..9859558
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIoSocketServerChannel.h
@@ -0,0 +1,98 @@
+#ifndef ossimPlanetIoSocketServerChannel_HEADER
+#define ossimPlanetIoSocketServerChannel_HEADER
+#include <ossimPlanet/netChannel.h>
+#include <ossimPlanet/ossimPlanetIo.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <osg/ref_ptr>
+#include <queue>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Timer>
+#include <iostream>
+
+class OSSIMPLANET_DLL ossimPlanetIoSocketServerChannel : public ossimPlanetIo,
+ public netChannel
+{
+public:
+ ossimPlanetIoSocketServerChannel();
+ virtual ~ossimPlanetIoSocketServerChannel();
+ virtual void searchName(ossimString& searchNameResult)const;
+ bool setSocket(const std::string& host,
+ int port,
+ const std::string& ioType);
+ virtual void setEnableFlag(bool flag);
+ virtual void clearAllBuffers();
+ const std::string& host()const;
+ const std::string& ioType()const;
+ int port()const;
+ bool isTcp()const;
+ virtual ossim_uint32 read(char* /* buffer */, ossim_uint32 /* bufferSize */,
+ ossimPlanetIo::IoResultType& ioResult)
+ {
+ ioResult = IO_NO_DATA;
+ return 0;
+ }
+ virtual ossim_uint32 write(const char* /* buffer */, ossim_uint32 /* bufferSize */,
+ ossimPlanetIo::IoResultType& ioResult)
+ {
+ ioResult = IO_NO_DATA;
+ return 0;
+ }
+ virtual void performIo();
+ virtual osg::ref_ptr<ossimPlanetMessage> popMessage();
+ int handle()
+ {
+ return getHandle();
+ }
+ virtual void closeIo()
+ {
+ netChannel::close();
+ }
+ virtual bool openIo()
+ {
+ closeIo();
+ return setSocket(theHost, thePort, theIoType);
+ }
+ void setAutoReconnectFlag(bool flag);
+ bool autoReconnectFlag()const;
+ void setAutoReconnectInterval(ossim_uint32 milliseconds);
+ ossim_uint32 autoReconnectInterval()const;
+
+ // these are the callback handlers and we can create new Sockets with the given handle and add it to the thread.
+
+ virtual void handleClose (void)
+ {
+// ulSetError(UL_WARNING,"Network: %d: unhandled close",getHandle());
+ }
+ virtual void handleRead (void); // for udp servers we can read
+ virtual void handleWrite (void);
+// {
+// ulSetError(UL_WARNING,"Network: %d: unhandled write",getHandle());
+// }
+ virtual void handleAccept (void);// for tcp servers we can accept
+ virtual void handleError (int error)
+ {
+ std::cout << "ossimPlanetIoSocketServerChannel::handleError() = " << error << std::endl;
+// ulSetError(UL_WARNING,"Network: %d: errno: %s(%d)",getHandle(),strerror(errno),errno);
+ }
+protected:
+ bool protectedFindHandle(int h)const;
+ bool protectedSetSocket(const std::string& host,
+ int port,
+ const std::string& ioType);
+ std::string theHost;
+ int thePort;
+ std::string theIoType;
+ bool theIsTcp;
+ ossimPlanetReentrantMutex theIoListMutex;
+ std::vector<osg::ref_ptr<ossimPlanetIo> > theIoList;
+ ossimPlanetReentrantMutex theInQueueMutex;
+ std::queue<osg::ref_ptr<ossimPlanetMessage> > theInQueue;
+ bool theAutoReconnectFlag;
+ ossim_uint32 theAutoReconnectInterval; // specified in milliseconds
+ osg::Timer_t theLastTick;
+ ossimPlanetReentrantMutex theSocketMutex;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetIoThread.h b/ossimPlanet/include/ossimPlanet/ossimPlanetIoThread.h
new file mode 100644
index 0000000..b5808e0
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetIoThread.h
@@ -0,0 +1,76 @@
+#ifndef ossimPlanetIoThread_HEADER
+#define ossimPlanetIoThread_HEADER
+#include <OpenThreads/Thread>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetIoMessageHandler.h>
+#include <osg/ref_ptr>
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetIo.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <queue>
+
+class OSSIMPLANET_DLL ossimPlanetIoThread : public OpenThreads::Thread,
+ public osg::Referenced,
+ public ossimPlanetActionReceiver
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetIoMessageHandler> > MessageHandlerListType;
+ ossimPlanetIoThread();
+ void addIo(osg::ref_ptr<ossimPlanetIo> io,
+ bool autoStartFlag = true);
+ virtual void execute(const ossimPlanetAction &a);
+ osg::ref_ptr<ossimPlanetIo> findIo(const ossimString& searchString);
+ const osg::ref_ptr<ossimPlanetIo> findIo(const ossimString& searchString)const;
+ /**
+ * broadcast to all outgoing sockets the passed in message
+ */
+ void sendMessage(osg::ref_ptr<ossimPlanetMessage> message, bool forceSendFlag=false);
+
+ /**
+ * push message onto the named object
+ */
+ bool sendMessage(const ossimString& searchName,
+ osg::ref_ptr<ossimPlanetMessage> message,
+ bool forceSendFlag=false);
+ osg::ref_ptr<ossimPlanetIo> removeIoGivenSearchString(const ossimString& searchString);
+ osg::ref_ptr<ossimPlanetIo> ioGivenSearchName(const ossimString& sarchString);
+ bool removeIo(osg::ref_ptr<ossimPlanetIo> io);
+ virtual void run();
+ int cancel();
+ bool addMessageHandler(osg::ref_ptr<ossimPlanetIoMessageHandler> handler);
+ bool removeMessageHandler(osg::ref_ptr<ossimPlanetIoMessageHandler> handler);
+ bool removeMessageHandler(const ossimString& handlerName);
+ ossim_uint32 ioCount()const;
+ void clearIo();
+ bool startedFlag()const;
+ void setStartedFlag(bool flag);
+ bool doneFlag()const;
+ void setDoneFlag(bool flag);
+ virtual void setPauseFlag(bool flag, bool waitTilPaused=true);
+ bool pauseFlag()const;
+ bool startCalledFlag()const;
+ void setStartCalledFlag(bool flag);
+ virtual void start();
+protected:
+ void handleMessage(osg::ref_ptr<ossimPlanetMessage> msg);
+ void delayedExecute(const ossimPlanetAction &a);
+ void delayedXmlExecute(const ossimPlanetXmlAction &a);
+
+ mutable ossimPlanetReentrantMutex thePropertyMutex;
+ mutable ossimPlanetReentrantMutex theIoListMutex;
+ std::vector<osg::ref_ptr<ossimPlanetIo> > theIoList;
+ mutable ossimPlanetReentrantMutex theMessageHandlerListMutex;
+ ossimPlanetIoThread::MessageHandlerListType theMessageHandlerList;
+ bool theDoneFlag;
+ bool theStartedFlag;
+
+ bool theStartCalledFlag;
+ bool thePauseFlag;
+ mutable ossimPlanetReentrantMutex theDelayedExecutionMutex;
+ std::queue<osg::ref_ptr<ossimPlanetAction> > theDelayedExecution;
+
+ ossimPlanetReentrantMutex theLoopMutex;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetJpegImage.h b/ossimPlanet/include/ossimPlanet/ossimPlanetJpegImage.h
new file mode 100644
index 0000000..bc47653
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetJpegImage.h
@@ -0,0 +1,24 @@
+#ifndef ossimPlanetJpegImage_HEADER
+#define ossimPlanetJpegImage_HEADER
+#include <iostream>
+#include "ossimPlanetExport.h"
+
+class ossimPlanetImage;
+class OSSIMPLANET_DLL ossimPlanetJpegImage
+{
+public:
+ ossimPlanetJpegImage();
+ virtual ~ossimPlanetJpegImage();
+ bool loadFile(std::string& inputFile,
+ ossimPlanetImage& image);
+ bool saveFile(std::string& outputFile,
+ ossimPlanetImage& image);
+
+ bool loadFile(std::istream& inputStream,
+ ossimPlanetImage& image);
+ bool saveFile( std::ostream& stream,
+ ossimPlanetImage &image,
+ bool verbose=false);
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKml.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKml.h
new file mode 100644
index 0000000..1ecdc2f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKml.h
@@ -0,0 +1,2553 @@
+#ifndef ossimPlanetKml_HEADER
+#define ossimPlanetKml_HEADER
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <osg/Vec3d>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/base/ossimHexString.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/BoundingSphere>
+
+inline OSSIMPLANET_DLL ossimPlanetKmlColorMode ossimPlanetKmlConvertColorMode(const ossimString& value)
+{
+ if(value == "normal")
+ {
+ return ossimPlanetKmlColorMode_NORMAL;
+ }
+ else if(value == "random")
+ {
+ return ossimPlanetKmlColorMode_RANDOM;
+ }
+
+ return ossimPlanetKmlColorMode_NONE;
+}
+
+inline OSSIMPLANET_DLL ossimPlanetKmlUnits ossimPlanetKmlConvertUnits(const ossimString& value)
+{
+ if(value == "fraction")
+ {
+ return ossimPlanetKmlUnits_FRACTION;
+ }
+ else if(value == "pixels")
+ {
+ return ossimPlanetKmlUnits_PIXELS;
+ }
+ else if(value == "insetPixels")
+ {
+ return ossimPlanetKmlUnits_INSET_PIXELS;
+ }
+
+ return ossimPlanetKmlUnits_NONE;
+}
+
+inline OSSIMPLANET_DLL ossimString ossimPlanetKmlConvertUnits(ossimPlanetKmlUnits value)
+{
+ switch(value)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ return "fraction";
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ return "pixels";
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ return "insetPixels";
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return "";
+}
+
+inline OSSIMPLANET_DLL ossimPlanetAltitudeMode ossimPlanetKmlConvertAltitudeMode(const ossimString& value)
+{
+ if((value == "clampToGround")||
+ (value == "clampedToGround"))
+ {
+ return ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ }
+ else if(value == "relativeToGround")
+ {
+ return ossimPlanetAltitudeMode_RELATIVE_TO_GROUND;
+ }
+ else if(value == "absolute")
+ {
+ return ossimPlanetAltitudeMode_ABSOLUTE;
+ }
+
+ return ossimPlanetAltitudeMode_NONE;
+}
+
+inline OSSIMPLANET_DLL ossimString ossimPlanetKmlConvertAltitudeMode(const ossimPlanetAltitudeMode& value)
+{
+ switch(value)
+ {
+ case ossimPlanetAltitudeMode_CLAMP_TO_GROUND:
+ {
+ return "clampToGround";
+ }
+ case ossimPlanetAltitudeMode_RELATIVE_TO_GROUND:
+ {
+ return "relativeToGround";
+ }
+ case ossimPlanetAltitudeMode_ABSOLUTE:
+ {
+ return "absolute";
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return "";
+}
+
+inline OSSIMPLANET_DLL ossimPlanetKmlRefreshMode ossimPlanetKmlConvertRefreshMode(const ossimString& value)
+{
+ ossimString temp(value);
+ temp = temp.downcase();
+
+ if(temp == "onchange")
+ {
+ return ossimPlanetKmlRefreshMode_ON_CHANGE;
+ }
+ else if(temp == "oninterval")
+ {
+ return ossimPlanetKmlRefreshMode_ON_INTERVAL;
+ }
+ else if(temp == "onexpire")
+ {
+ return ossimPlanetKmlRefreshMode_ON_EXPIRE;
+ }
+
+ return ossimPlanetKmlRefreshMode_NONE;
+}
+
+inline OSSIMPLANET_DLL ossimString ossimPlanetKmlConvertRefreshMode(ossimPlanetKmlViewRefreshMode value)
+{
+ switch(value)
+ {
+ case ossimPlanetKmlRefreshMode_ON_CHANGE:
+ {
+ return "onChange";
+ }
+ case ossimPlanetKmlRefreshMode_ON_INTERVAL:
+ {
+ return "onInterval";
+ }
+ case ossimPlanetKmlRefreshMode_ON_EXPIRE:
+ {
+ return "onExpire";
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return "";
+}
+
+inline OSSIMPLANET_DLL ossimPlanetKmlViewRefreshMode ossimPlanetKmlConvertViewRefreshMode(const ossimString& value)
+{
+ ossimString temp(value);
+ temp = temp.downcase();
+
+ if(temp == "never")
+ {
+ return ossimPlanetKmlViewRefreshMode_NEVER;
+ }
+ else if(temp == "onrequest")
+ {
+ return ossimPlanetKmlViewRefreshMode_ON_REQUEST;
+ }
+ else if(temp == "onstop")
+ {
+ return ossimPlanetKmlViewRefreshMode_ON_STOP;
+ }
+ else if(temp == "onregion")
+ {
+ return ossimPlanetKmlViewRefreshMode_ON_REGION;
+ }
+
+ return ossimPlanetKmlViewRefreshMode_NONE;
+}
+
+inline OSSIMPLANET_DLL ossimString ossimPlanetKmlConvertViewRefreshMode(ossimPlanetKmlViewRefreshMode value)
+{
+ switch(value)
+ {
+ case ossimPlanetKmlViewRefreshMode_NEVER:
+ {
+ return "never";
+ }
+ case ossimPlanetKmlViewRefreshMode_ON_REQUEST:
+ {
+ return "onRequest";
+ }
+ case ossimPlanetKmlViewRefreshMode_ON_STOP:
+ {
+ return "onStop";
+ }
+ case ossimPlanetKmlViewRefreshMode_ON_REGION:
+ {
+ return "onRegion";
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return "never";
+}
+
+inline OSSIMPLANET_DLL void ossimPlanetKmlColorToRGBA(ossim_uint8& r,
+ ossim_uint8& g,
+ ossim_uint8& b,
+ ossim_uint8& a,
+ const ossimString& colorString)
+{
+ r = 255;
+ g = 255;
+ b = 255;
+ a = 255;
+ if(colorString.size() == 8)
+ {
+ a = ossimHexString(colorString.begin(),
+ colorString.begin()+2).toUchar();
+ b = ossimHexString(colorString.begin()+2,
+ colorString.begin()+4).toUchar();
+ g = ossimHexString(colorString.begin()+4,
+ colorString.begin()+6).toUchar();
+ r = ossimHexString(colorString.begin()+6,
+ colorString.begin()+8).toUchar();
+ }
+ else if(colorString.size() == 6)
+ {
+ b = ossimHexString(colorString.begin(),
+ colorString.begin()+2).toUchar();
+ g = ossimHexString(colorString.begin()+2,
+ colorString.begin()+4).toUchar();
+ r = ossimHexString(colorString.begin()+4,
+ colorString.begin()+6).toUchar();
+ a = 255;
+ }
+}
+
+class ossimPlanetKmlPoint;
+class ossimPlanetKmlLineString;
+class ossimPlanetKmlLinearRing;
+class ossimPlanetKmlPolygon;
+class ossimPlanetKmlMultiGeometry;
+class ossimPlanetKmlModel;
+class ossimPlanetKmlFeature;
+
+/**
+ * This is an abstract base class and cannot be used directly in a KML file.
+ * It provides the id attribute, which allows unique identification of a KML element,
+ * and the targetId attribute, which is used to reference objects that have already
+ * been loaded into Planet. The id attribute must be assigned if the <Update> mechanism is to be used.
+ */
+class OSSIMPLANET_DLL ossimPlanetKmlObject : public osg::Referenced
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetKmlObject> > ObjectList;
+ ossimPlanetKmlObject()
+ {
+ theId = "";
+ theTargetId = "";
+ theParent = 0;
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode)=0;
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const=0;
+ void setId(const ossimString& id)
+ {
+ theId = id;
+ }
+ const ossimString& id()
+ {
+ return theId;
+ }
+
+ void setTargetId(const ossimString& targetId)
+ {
+ theTargetId = targetId;
+ }
+
+ const ossimString& targetId()const
+ {
+ return theTargetId;
+ }
+ ossimPlanetKmlObject::ObjectList& getObjectList()
+ {
+ return theObjectList;
+ }
+ const ossimPlanetKmlObject::ObjectList& getObjectList()const
+ {
+ return theObjectList;
+ }
+ void setParent(ossimPlanetKmlObject* parent)
+ {
+ theParent = parent;
+ }
+ ossimPlanetKmlObject* getParent()
+ {
+ return theParent;
+ }
+ const ossimPlanetKmlObject* getParent()const
+ {
+ return theParent;
+ }
+ static ossimPlanetKmlObject* getRoot(ossimPlanetKmlObject* start);
+ static const ossimPlanetKmlObject* getRoot(const ossimPlanetKmlObject* start);
+ ossimFilename getCacheLocation(bool sharedLocationFlag = false)const;
+ virtual ossimFilename getKmlFile()const;
+protected:
+ ossimPlanetKmlObject* theParent;
+ ossimPlanetKmlObject::ObjectList theObjectList;
+ ossimString theId;
+ ossimString theTargetId;
+};
+
+/**
+ * Lod is an abbreviation for Level of Detail. <Lod> describes the size of the projected
+ * region on the screen that is required in order for the region to be considered
+ * "active." Also specifies the size of the pixel ramp used for fading in
+ * (from transparent to opaque) and fading out (from opaque to transparent).
+ */
+class OSSIMPLANET_DLL ossimPlanetKmlLod: public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlLod()
+ :theMinLodPixels(0),
+ theMaxLodPixels(-1),
+ theMinFadeExtent(0),
+ theMaxFadeExtent(0)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+
+ ossim_int32 minLodPixels()const
+ {
+ return theMinLodPixels;
+ }
+ void setMinLodPixels(ossim_int32 minLod)
+ {
+ theMinLodPixels = minLod;
+ }
+ ossim_int32 maxLodPixels()const
+ {
+ return theMaxLodPixels;
+ }
+ ossim_int32 minFadeExtent()const
+ {
+ return theMinFadeExtent;
+ }
+ void setMinFadeExtent(ossim_int32 minFade)
+ {
+ theMinFadeExtent = minFade;
+ }
+ ossim_int32 maxFadeExtent()const
+ {
+ return theMaxFadeExtent;
+ }
+ void setMaxFadeExtent(ossim_int32 maxFade)
+ {
+ theMaxFadeExtent = maxFade;
+ }
+protected:
+ void clearFields()
+ {
+ theMinLodPixels = 0;
+ theMaxLodPixels = -1;
+ theMinFadeExtent = 0;
+ theMaxFadeExtent = 0;
+ }
+ /**
+ *<minLodPixels> (default = 0) Measurement in screen pixels
+ * that represents the minimum limit of the visibility range for a
+ * given Region. Google Earth calculates the size of the Region when
+ * projected onto screen space. Then it computes the square root of
+ * the Region's area (if, for example, the Region is square and the
+ * viewpoint is directly above the Region, and the Region is not tilted,
+ * this measurement is equal to the width of the projected Region).
+ * If this measurement falls within the limits defined by
+ * <minLodPixels> and <maxLodPixels> (and if the <LatLonAltBox> is in view),
+ * the Region is active. If this limit is not reached, the associated geometry
+ * is considered to be too far from the user's viewpoint to be drawn.
+ */
+ ossim_int32 theMinLodPixels;
+
+ /**
+ *
+ * <maxLodPixels> (default = -1) Measurement in screen pixels that
+ * represents the maximum limit of the visibility range for a given Region.
+ * A value of -1, the default, indicates "active to infinite size."
+ */
+ ossim_int32 theMaxLodPixels;
+
+ /**
+ * <minFadeExtent> (default = 0) Distance over which the geometry fades,
+ * from fully opaque to fully transparent. This ramp value,
+ * expressed in screen pixels, is applied at the minimum end of the LOD (visibility) limits.
+ */
+ ossim_int32 theMinFadeExtent;
+
+ /**
+ * <maxFadeExtent> (default = 0) Distance over which the geometry fades,
+ * from fully transparent to fully opaque. This ramp value, expressed in
+ * screen pixels, is applied at the maximum end of the LOD (visibility) limits.
+ */
+ ossim_int32 theMaxFadeExtent;
+};
+
+/**
+ * Scales a model along the x, y, and z axes in the model's coordinate space.
+ */
+class OSSIMPLANET_DLL ossimPlanetKmlScale: public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlScale()
+ :ossimPlanetKmlObject(),
+ theX(1.0),
+ theY(1.0),
+ theZ(1.0)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void setX(double x)
+ {
+ theX = x;
+ }
+ double x()const
+ {
+ return theX;
+ }
+
+ void setY(double y)
+ {
+ theY = y;
+ }
+ double y()const
+ {
+ return theY;
+ }
+
+ void setZ(double z)
+ {
+ theZ = z;
+ }
+ double z()const
+ {
+ return theZ;
+ }
+protected:
+ void clearFields()
+ {
+ theX = 1.0;
+ theY = 1.0;
+ theZ = 1.0;
+ }
+
+ double theX;
+ double theY;
+ double theZ;
+};
+
+/**
+ * Specifies the exact coordinates of the Model's origin in latitude, longitude,
+ * and altitude. Latitude and longitude measurements are standard lat-lon projection
+ * with WGS84 datum.
+ */
+class OSSIMPLANET_DLL ossimPlanetKmlLocation: public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlLocation()
+ :ossimPlanetKmlObject(),
+ theLongitude(0.0),
+ theLatitude(0.0),
+ theAltitude(0.0)
+ {
+ }
+ ossimPlanetKmlLocation(const ossimPlanetKmlLocation& src)
+ :ossimPlanetKmlObject(src),
+ theLongitude(src.theLongitude),
+ theLatitude(src.theLatitude),
+ theAltitude(src.theAltitude)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void setLongitude(double lon)
+ {
+ theLongitude = lon;
+ }
+ double longitude()const
+ {
+ return theLongitude;
+ }
+
+ void setLatitude(double lat)
+ {
+ theLatitude = lat;
+ }
+ double latitude()const
+ {
+ return theLatitude;
+ }
+
+ void setAltitude(double altitude)
+ {
+ theAltitude = altitude;
+ }
+ double altitude()const
+ {
+ return theAltitude;
+ }
+protected:
+ void clearFields()
+ {
+ theLongitude = 0.0;
+ theLatitude = 0.0;
+ theAltitude = 0.0;
+ }
+ double theLongitude;
+ double theLatitude;
+ double theAltitude;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlOrientation : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlOrientation()
+ :ossimPlanetKmlObject(),
+ theHeading(0.0),
+ thePitch(0.0),
+ theRoll(0.0)
+ {
+ }
+ ossimPlanetKmlOrientation(const ossimPlanetKmlOrientation& src)
+ :ossimPlanetKmlObject(src),
+ theHeading(src.theHeading),
+ thePitch(src.thePitch),
+ theRoll(src.theRoll)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void setHeading(double h)
+ {
+ theHeading = h;
+ }
+ double heading()const
+ {
+ return theHeading;
+ }
+ void setPitch(double p)
+ {
+ thePitch = p;
+ }
+ double pitch()const
+ {
+ return thePitch;
+ }
+ void setRoll(double r)
+ {
+ theRoll = r;
+ }
+ double roll()const
+ {
+ return theRoll;
+ }
+protected:
+ void clearFields()
+ {
+ theHeading = 0.0;
+ thePitch = 0.0;
+ theRoll = 0.0;
+ }
+ double theHeading;
+ double thePitch;
+ double theRoll;
+};
+
+
+/**
+ * Specifies where the top, bottom, right, and left sides of a bounding box for the
+ * ground overlay are aligned. The <north>, <south>, <east>, and <west> elements are required.
+ * <north> (required) Specifies the latitude of the north edge of the bounding box,
+ * in decimal degrees from 0 to ±90.
+ * <south> (required) Specifies the latitude of the south edge of the bounding box,
+ * in decimal degrees from 0 to ±90.
+ * <east> (required) Specifies the longitude of the east edge of the bounding box,
+ * in decimal degrees from 0 to ±180. (For overlays that overlap the meridian of 180 longitude, values can extend beyond that range.)
+ * <west> (required) Specifies the longitude of the west edge of the bounding box,
+ * in decimal degrees from 0 to ±180. (For overlays that overlap the meridian of 180 longitude,
+ * values can extend beyond that range.)
+ * <rotation> (optional) specifies a rotation of the overlay about its center,
+ * in degrees. Values can be ±180. The default is 0 (north). Rotations are specified in a clockwise direction.
+ */
+class OSSIMPLANET_DLL ossimPlanetKmlLatLonBox : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlLatLonBox()
+ :ossimPlanetKmlObject()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theNorth = 0.0;
+ theSouth = 0.0;
+ theEast = 0.0;
+ theWest = 0.0;
+ theRotation = 0.0;
+ }
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ alt = 0.0;
+ lat = (theNorth+theSouth)*0.5;
+ lon = (theEast+theWest)*0.5;
+
+ return true;
+ }
+ void setBounds(double north, double south,
+ double east, double west)
+ {
+ theNorth = north;
+ theSouth = south;
+ theEast = east;
+ theWest = west;
+ }
+ void setNorth(double n)
+ {
+ theNorth = n;
+ }
+ double north()const
+ {
+ return theNorth;
+ }
+ void setSouth(double s)
+ {
+ theSouth = s;
+ }
+ double south()const
+ {
+ return theSouth;
+ }
+ void setEast(double e)
+ {
+ theEast = e;
+ }
+ double east()const
+ {
+ return theEast;
+ }
+
+ void setRotation(double rotation)
+ {
+ theRotation = rotation;
+ }
+ double rotation()const
+ {
+ return theRotation;
+ }
+protected:
+
+ double theNorth;
+ double theSouth;
+ double theEast;
+ double theWest;
+ double theRotation;
+};
+
+
+/**
+ * <LatLonAltBox>
+ *
+ * A bounding box that describes an area of interest
+ * defined by geographic coordinates and altitudes.
+ * Default values and required fields are as follows:
+ *
+ * Adds the following tags to LatLonBox:
+ *
+ * <altitudeMode> (defaults to clampToGround).
+ * Possible values are clampToGround, relativeToGround, and absolute.
+ * <minAltitude> Defaults to 0; specified in meters above sea level (and is affected by
+ * the <altitudeMode> specification).
+ * <maxAltitude> Defaults to 0; specified in meters above sea level
+ * (and is affected by the <altitudeMode> specification).
+ */
+class OSSIMPLANET_DLL ossimPlanetKmlLatLonAltBox : public ossimPlanetKmlLatLonBox
+{
+public:
+ ossimPlanetKmlLatLonAltBox()
+ :ossimPlanetKmlLatLonBox()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theMinAltitude = 0.0;
+ theMaxAltitude = 0.0;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ }
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ alt = (theMinAltitude+theMaxAltitude)*0.5;
+ lat = (theNorth+theSouth)*0.5;
+ lon = (theEast+theWest)*0.5;
+
+ return true;
+ }
+ void setBounds(double north, double south,
+ double east, double west,
+ double minAlt=0.0, double maxAlt=0.0)
+ {
+ ossimPlanetKmlLatLonBox::setBounds(north, south, east, west);
+ theMinAltitude = minAlt;
+ theMaxAltitude = maxAlt;
+ }
+ void setMinAltitude(double minAlt)
+ {
+ theMinAltitude = minAlt;
+ }
+ double minAltitude()const
+ {
+ return theMinAltitude;
+ }
+ void setMaxAltitude(double maxAlt)
+ {
+ theMaxAltitude = maxAlt;
+ }
+ double maxAltitude()const
+ {
+ return theMaxAltitude;
+ }
+ ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+
+protected:
+ double theMinAltitude;
+ double theMaxAltitude;
+ ossimPlanetAltitudeMode theAltitudeMode;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLink : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlLink()
+ :ossimPlanetKmlObject()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theHref = "";
+ theRefreshMode = ossimPlanetKmlRefreshMode_ON_CHANGE;
+ theRefreshInterval = 4.0;
+ theViewRefreshMode = ossimPlanetKmlViewRefreshMode_NEVER;
+ theViewRefreshTime = 4.0;
+ theViewBoundScale = 1.0;
+ theViewFormat = "";
+ theHttpQuery = "";
+ }
+ void setHref(const ossimString& ref)
+ {
+ theHref = ref;
+ }
+ const ossimString href()const
+ {
+ return theHref;
+ }
+
+ void setRefreshMode(ossimPlanetKmlRefreshMode refreshMode)
+ {
+ theRefreshMode = refreshMode;
+ }
+ ossimPlanetKmlRefreshMode refreshMode()const
+ {
+ return theRefreshMode;
+ }
+
+ double refreshInterval()const
+ {
+ return theRefreshInterval;
+ }
+ void setRefreshInterval(double interval)
+ {
+ theRefreshInterval = interval;
+ }
+
+ void setViewRefreshMode(ossimPlanetKmlViewRefreshMode mode)
+ {
+ theViewRefreshMode = mode;
+ }
+ ossimPlanetKmlViewRefreshMode viewRefreshMode()const
+ {
+ return theViewRefreshMode;
+ }
+
+ void setViewRefreshTime(double time)
+ {
+ theViewRefreshTime = time;
+ }
+ double viewRefreshTime()const
+ {
+ return theViewRefreshTime;
+ }
+
+ void setViewBoundScale(double scale)
+ {
+ theViewBoundScale = scale;
+ }
+ double viewBoundScale()const
+ {
+ return theViewBoundScale;
+ }
+
+ void setViewFormat(const ossimString& value)
+ {
+ theViewFormat = value;
+ }
+ const ossimString& viewFormat()const
+ {
+ return theViewFormat;
+ }
+ void setHttpQuery(const ossimString& value)
+ {
+ theHttpQuery = value;
+ }
+ const ossimString& httpQuery()const
+ {
+ return theHttpQuery;
+ }
+ virtual ossimFilename download(bool forceOverwrite=false,
+ const ossimFilename& locationOverride=ossimFilename(""))const;
+
+protected:
+
+ ossimString theHref;
+ ossimPlanetKmlRefreshMode theRefreshMode;
+ double theRefreshInterval;
+ ossimPlanetKmlViewRefreshMode theViewRefreshMode;
+ double theViewRefreshTime;
+ double theViewBoundScale;
+ ossimString theViewFormat;
+ ossimString theHttpQuery;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlIcon : public ossimPlanetKmlLink
+{
+public:
+ ossimPlanetKmlIcon()
+ :ossimPlanetKmlLink()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlRegion : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlRegion()
+ :ossimPlanetKmlObject()
+ {
+
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ lat = 0.0;
+ lon = 0.0;
+ alt = 0.0;
+ if(theBox.valid())
+ {
+ return theBox->getCenter(lat, lon, alt);
+ }
+ return false;
+ }
+ void setBounds(double north, double south,
+ double east, double west,
+ double minAlt=0.0, double maxAlt=0.0)
+ {
+ if(!theBox.valid())
+ {
+ theBox = new ossimPlanetKmlLatLonAltBox;
+ }
+ theBox->setBounds(north, south, east, west, minAlt, maxAlt);
+ }
+ void setBox(osg::ref_ptr<ossimPlanetKmlLatLonAltBox> box)
+ {
+ theBox = box.get();
+ }
+ const osg::ref_ptr<ossimPlanetKmlLatLonAltBox> box()const
+ {
+ return theBox.get();
+ }
+ void setLod(osg::ref_ptr<ossimPlanetKmlLod> lod)
+ {
+ theLod = lod.get();
+ }
+ const osg::ref_ptr<ossimPlanetKmlLod> lod()const
+ {
+ return theLod.get();
+ }
+protected:
+ void clearFields()
+ {
+ theLod = 0;
+ theBox = 0;
+ }
+ osg::ref_ptr<ossimPlanetKmlLod> theLod;
+ osg::ref_ptr<ossimPlanetKmlLatLonAltBox> theBox;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLookAt : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlLookAt()
+ :ossimPlanetKmlObject()
+ {
+ theLookAt = new ossimPlanetLookAt();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void setAll(double lat, double lon, double altitude,
+ double heading, double pitch, double range,
+ const ossimString& mode="clampToGround")
+ {
+ theLookAt->setAll(lat, lon, altitude, heading, pitch, 0.0, range,
+ ossimPlanetLookAt::modeFromString(mode));
+ }
+
+
+ osg::ref_ptr<ossimPlanetLookAt> lookAt()
+ {
+ return theLookAt;
+ }
+ const osg::ref_ptr<ossimPlanetLookAt> lookAt()const
+ {
+ return theLookAt;
+ }
+
+ void clearFields()
+ {
+ setAll(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, "clampToGround");
+ }
+ double latitude()const
+ {
+ return theLookAt->lat();
+ }
+ double longitude()const
+ {
+ return theLookAt->lon();
+ }
+ double altitude()const
+ {
+ return theLookAt->altitude();
+ }
+ double heading()const
+ {
+ return theLookAt->heading();
+ }
+ double pitch()const
+ {
+ return theLookAt->pitch();
+ }
+ double roll()const
+ {
+ return theLookAt->roll();
+ }
+ double range()const
+ {
+ return theLookAt->range();
+ }
+ void setAlititudeMode(ossimPlanetAltitudeMode mode)
+ {
+ theLookAt->setAltitudeMode(mode);
+ }
+ ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theLookAt->altitudeMode();
+ }
+protected:
+ osg::ref_ptr<ossimPlanetLookAt> theLookAt;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlTimePrimitive : public ossimPlanetKmlObject
+{
+public:
+/* static ossimData toDate(const ossimString& formatString); */
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlTimeSpan : public ossimPlanetKmlTimePrimitive
+{
+public:
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void clearFields()
+ {
+ theBegin = "";
+ theEnd = "";
+ }
+protected:
+ ossimString theBegin;
+ ossimString theEnd;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlTimeStamp : public ossimPlanetKmlTimePrimitive
+{
+public:
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void clearFields()
+ {
+ theWhen = "";
+ }
+protected:
+ ossimString theWhen;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlColorStyle : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlColorStyle()
+ :ossimPlanetKmlObject(),
+ theColor("ffffffff"),
+ theColorMode(ossimPlanetKmlColorMode_NORMAL)
+ {
+ }
+
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theColor = "";
+ theColorMode = ossimPlanetKmlColorMode_NORMAL;
+ }
+
+ const ossimString& color()const
+ {
+ return theColor;
+ }
+
+ ossimPlanetKmlColorMode colorMode()const
+ {
+ return theColorMode;
+ }
+
+public:
+ ossimString theColor;
+ ossimPlanetKmlColorMode theColorMode;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLineStyle : public ossimPlanetKmlColorStyle
+{
+public:
+ ossimPlanetKmlLineStyle()
+ :ossimPlanetKmlColorStyle(),
+ theWidth(1)
+ {
+ }
+
+ bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ ossim_float32 width()const
+ {
+ return theWidth;
+ }
+ void clearFields()
+ {
+ theWidth = 1.0;
+ }
+
+protected:
+ ossim_float32 theWidth;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlPolyStyle : public ossimPlanetKmlColorStyle
+{
+public:
+ ossimPlanetKmlPolyStyle()
+ :ossimPlanetKmlColorStyle(),
+ theFillFlag(true),
+ theOutlineFlag(true)
+ {
+ }
+
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ bool getFillFlag()const
+ {
+ return theFillFlag;
+ }
+ bool getOutlineFlag()const
+ {
+ return theOutlineFlag;
+ }
+ void clearFields()
+ {
+ theFillFlag = true;
+ theOutlineFlag = true;
+ }
+protected:
+ bool theFillFlag;
+ bool theOutlineFlag;
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetKmlIconStyle : public ossimPlanetKmlColorStyle
+{
+public:
+ ossimPlanetKmlIconStyle()
+ :ossimPlanetKmlColorStyle(),
+ theScale(1.0),
+ theHeading(0.0),
+ theXHotspot(.5),
+ theYHotspot(.5),
+ theXUnits(ossimPlanetKmlUnits_FRACTION),
+ theYUnits(ossimPlanetKmlUnits_FRACTION)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theScale = 1.0;
+ theHeading = 1.0;
+ theIcon = 0;
+ theXHotspot = .5;
+ theYHotspot = .5;
+ theXUnits = ossimPlanetKmlUnits_FRACTION;
+ }
+ osg::ref_ptr<ossimPlanetKmlIcon> icon()
+ {
+ return theIcon;
+ }
+ const osg::ref_ptr<ossimPlanetKmlIcon> icon()const
+ {
+ return theIcon;
+ }
+
+ double xHotSpot()const
+ {
+ return theXHotspot;
+ }
+ double yHotspot()const
+ {
+ return theYHotspot;
+ }
+ double heading()const
+ {
+ return theHeading;
+ }
+ double scale()const
+ {
+ return theScale;
+ }
+ ossimPlanetKmlUnits xUnits()const
+ {
+ return theXUnits;
+ }
+ ossimPlanetKmlUnits yUnits()const
+ {
+ return theYUnits;
+ }
+
+protected:
+ float theScale;
+ float theHeading;
+ osg::ref_ptr<ossimPlanetKmlIcon> theIcon;
+ float theXHotspot;
+ float theYHotspot;
+ ossimPlanetKmlUnits theXUnits;
+ ossimPlanetKmlUnits theYUnits;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLabelStyle : public ossimPlanetKmlColorStyle
+{
+public:
+ ossimPlanetKmlLabelStyle()
+ :ossimPlanetKmlColorStyle(),
+ theScale(1.0)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void setScale(float scale)
+ {
+ theScale = scale;
+ }
+ float scale()const
+ {
+ return theScale;
+ }
+ void clearFields()
+ {
+ theScale = 1.0;
+ }
+protected:
+ float theScale;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlBalloonStyle : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlBalloonStyle()
+ :ossimPlanetKmlObject(),
+ theBackgroundColor("ffffffff"),
+ theTextColor("ff000000"),
+ theText("")
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ const ossimString& backgroundColor()const
+ {
+ return theBackgroundColor;
+ }
+ const ossimString& textColor()const
+ {
+ return theTextColor;
+ }
+ const ossimString& text()const
+ {
+ return theText;
+ }
+ void clearFields()
+ {
+ theBackgroundColor = "ffffffff";
+ theTextColor = "ff000000";
+ theText = "";
+ }
+protected:
+ ossimString theBackgroundColor;
+ ossimString theTextColor;
+ ossimString theText;
+};
+
+class ossimPlanetKmlStyle;
+class ossimPlanetKmlStyleMap;
+class OSSIMPLANET_DLL ossimPlanetKmlStyleSelector : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlStyleSelector()
+ :ossimPlanetKmlObject()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+ {
+ return ossimPlanetKmlObject::parse(xmlNode);
+ }
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const
+ {
+ ossimPlanetKmlObject::write(xmlNode);
+ }
+ virtual const ossimPlanetKmlStyle* toStyle()const
+ {
+ return 0;
+ }
+ virtual ossimPlanetKmlStyle* toStyle()
+ {
+ return 0;
+ }
+ virtual const ossimPlanetKmlStyleMap* toStyleMap()const
+ {
+ return 0;
+ }
+ virtual ossimPlanetKmlStyleMap* toStyleMap()
+ {
+ return 0;
+ }
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlStyle : public ossimPlanetKmlStyleSelector
+{
+public:
+ ossimPlanetKmlStyle()
+ :ossimPlanetKmlStyleSelector()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual const ossimPlanetKmlStyle* toStyle()const
+ {
+ return this;
+ }
+ virtual ossimPlanetKmlStyle* toStyle()
+ {
+ return this;
+ }
+
+ void clearFields()
+ {
+ theIconStyle = 0;
+ theLabelStyle = 0;
+ theLineStyle = 0;
+ thePolyStyle = 0;
+ }
+ void setIconStyle(osg::ref_ptr<ossimPlanetKmlIconStyle> value)
+ {
+ theIconStyle = value;
+ }
+ const osg::ref_ptr<ossimPlanetKmlIconStyle> iconStyle()const
+ {
+ return theIconStyle.get();
+ }
+ void setLabelStyle(osg::ref_ptr<ossimPlanetKmlLabelStyle> value)
+ {
+ theLabelStyle = value;
+ }
+ const osg::ref_ptr<ossimPlanetKmlLabelStyle> labelStyle()const
+ {
+ return theLabelStyle.get();
+ }
+ void setLineStyle(osg::ref_ptr<ossimPlanetKmlLineStyle> value)
+ {
+ theLineStyle = value;
+ }
+ const osg::ref_ptr<ossimPlanetKmlLineStyle> lineStyle()const
+ {
+ return theLineStyle.get();
+ }
+ void setPolyStyle(osg::ref_ptr<ossimPlanetKmlPolyStyle> value)
+ {
+ thePolyStyle = value;
+ }
+ const osg::ref_ptr<ossimPlanetKmlPolyStyle> polyStyle()const
+ {
+ return thePolyStyle.get();
+ }
+ void setBalloonStyle(osg::ref_ptr<ossimPlanetKmlBalloonStyle> value)
+ {
+ theBalloonStyle = value;
+ }
+ const osg::ref_ptr<ossimPlanetKmlBalloonStyle> balloonStyle()const
+ {
+ return theBalloonStyle.get();
+ }
+
+protected:
+ osg::ref_ptr<ossimPlanetKmlIconStyle> theIconStyle;
+ osg::ref_ptr<ossimPlanetKmlLabelStyle> theLabelStyle;
+ osg::ref_ptr<ossimPlanetKmlLineStyle> theLineStyle;
+ osg::ref_ptr<ossimPlanetKmlPolyStyle> thePolyStyle;
+ osg::ref_ptr<ossimPlanetKmlBalloonStyle> theBalloonStyle;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlStyleMap : public ossimPlanetKmlStyleSelector
+{
+public:
+ typedef std::map<std::string, std::string> MapType;
+
+ ossimPlanetKmlStyleMap()
+ :ossimPlanetKmlStyleSelector()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void clearFields()
+ {
+ theStyleMap.clear();
+ }
+ virtual const ossimPlanetKmlStyleMap* toStyleMap()const
+ {
+ return this;
+ }
+ virtual ossimPlanetKmlStyleMap* toStyleMap()
+ {
+ return this;
+ }
+ void styles(std::vector<ossimString>& styleNames)const
+ {
+ MapType::const_iterator i = theStyleMap.begin();
+ while(i!=theStyleMap.end())
+ {
+ styleNames.push_back(i->first);
+ ++i;
+ }
+ }
+ ossimString findStyle(const ossimString& styleName)const
+ {
+ MapType::const_iterator i = theStyleMap.find(styleName);
+ if(i != theStyleMap.end())
+ {
+ return i->second;
+ }
+ return "";
+ }
+ ossimString normalUrl()const
+ {
+ return findStyle("normal");
+ }
+ ossimString highlightUrl()const
+ {
+ return findStyle("highlight");
+ }
+protected:
+/* ossimString theNormalUrl; */
+/* ossimString theHighlightUrl; */
+ MapType theStyleMap;
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetKmlFeature : public ossimPlanetKmlObject
+{
+public:
+ ossimPlanetKmlFeature()
+ :ossimPlanetKmlObject()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theName = "";
+ theVisibilityFlag = true;
+ theOpenFlag = true;
+ theAddress = "";
+ thePhoneNumber = "";
+ theDescription = "";
+ theCDataDescriptionFlag = false;
+ theLookAt = 0;
+ theStyleUrl = "";
+ theStyleSelector = 0;
+ theRegion = 0;
+ theExtendedData = 0;
+ }
+ void setName(const ossimString& name)
+ {
+ theName = name;
+ }
+ const ossimString& name()const
+ {
+ return theName;
+ }
+ bool visibilityFlag()const
+ {
+ return theVisibilityFlag;
+ }
+ void setVisibilityFlag(bool flag)
+ {
+ theVisibilityFlag = flag;
+ }
+ void setOpenFlag(bool flag)
+ {
+ theOpenFlag = flag;
+ }
+ bool openFlag()const
+ {
+ return theOpenFlag;
+ }
+ void setAddress(const ossimString& address)
+ {
+ theAddress = address;
+ }
+ const ossimString& address()const
+ {
+ return theAddress;
+ }
+ void setPhoneNumber(const ossimString& phoneNumber)
+ {
+ thePhoneNumber = phoneNumber;
+ }
+ const ossimString& phoneNumber()const
+ {
+ return thePhoneNumber;
+ }
+ void setDescription(const ossimString& description)
+ {
+ theDescription = description;
+ }
+ const ossimString& description()const
+ {
+ return theDescription;
+ }
+ void setLookAt(osg::ref_ptr<ossimPlanetKmlLookAt> lookAt)
+ {
+ theLookAt = lookAt.get();
+ }
+ const osg::ref_ptr<ossimPlanetKmlLookAt> lookAt()const
+ {
+ return theLookAt;
+ }
+ void setSyleUrl(const ossimString& styleUrl)
+ {
+ theStyleUrl = styleUrl;
+ }
+ const ossimString& styleUrl()const
+ {
+ return theStyleUrl;
+ }
+ void setRegion(osg::ref_ptr<ossimPlanetKmlRegion> region)
+ {
+ theRegion = region.get();
+ }
+ osg::ref_ptr<ossimPlanetKmlRegion> region()const
+ {
+ return theRegion;
+ }
+ void setExtendedData(ossimRefPtr<ossimXmlNode> value)
+ {
+ theExtendedData = value;
+ }
+ const ossimXmlNode* extendedData()const
+ {
+ return theExtendedData.get();
+ }
+ ossimXmlNode* extendedData()
+ {
+ return theExtendedData.get();
+ }
+
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ lat = 0.0;
+ lon = 0.0;
+ alt = 0.0;
+
+ if(theRegion.valid())
+ {
+ return theRegion->getCenter(lat, lon, alt);
+ }
+ return false;
+ }
+
+ const osg::ref_ptr<ossimPlanetKmlStyleSelector> getStyleSelector()const
+ {
+ return theStyleSelector;
+ }
+protected:
+ ossimString theName;
+ bool theVisibilityFlag;
+ bool theOpenFlag;
+ ossimString theAddress;
+ // there is an Address details field. Need to look at it later.
+
+ // End details field
+
+ ossimString thePhoneNumber;
+ ossimString theSnippet;
+ ossimString theSnippetMaxLines;
+ ossimString theDescription;
+ bool theCDataDescriptionFlag;
+ osg::ref_ptr<ossimPlanetKmlLookAt> theLookAt;
+ osg::ref_ptr<ossimPlanetKmlTimePrimitive> theTimePrimitive;
+ ossimString theStyleUrl;
+ osg::ref_ptr<ossimPlanetKmlStyleSelector> theStyleSelector;
+ osg::ref_ptr<ossimPlanetKmlRegion> theRegion;
+ ossimRefPtr<ossimXmlNode> theExtendedData;
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetKmlGeometry : public ossimPlanetKmlObject
+{
+public:
+ typedef std::vector<osg::Vec3d> PointListType;
+
+ ossimPlanetKmlGeometry()
+ :ossimPlanetKmlObject()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual bool getCenter(double& lat, double& lon, double& alt)const=0;
+ virtual ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return ossimPlanetAltitudeMode_NONE;
+ }
+
+ virtual ossimPlanetKmlPoint* toPoint(){return 0;}
+ virtual const ossimPlanetKmlPoint* toPoint()const{return 0;}
+ virtual ossimPlanetKmlLineString* toLineString(){return 0;}
+ virtual const ossimPlanetKmlLineString* toLineString()const{return 0;}
+ virtual ossimPlanetKmlLinearRing* toLinearRing(){return 0;}
+ virtual const ossimPlanetKmlLinearRing* toLinearRing()const{return 0;}
+ virtual ossimPlanetKmlPolygon* toPolygon(){return 0;}
+ virtual const ossimPlanetKmlPolygon* toPolygon()const{return 0;}
+ virtual ossimPlanetKmlMultiGeometry* toMultiGeometry(){return 0;}
+ virtual const ossimPlanetKmlMultiGeometry* toMultiGeometry()const{return 0;}
+ virtual ossimPlanetKmlModel* toModel(){return 0;}
+ virtual const ossimPlanetKmlModel* toModel()const{return 0;}
+
+ static void computeCenter(osg::Vec3d& result,
+ const PointListType& pointList);
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlPoint : public ossimPlanetKmlGeometry
+{
+public:
+ ossimPlanetKmlPoint()
+ :ossimPlanetKmlGeometry()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ if(thePointList.size() > 0)
+ {
+ lat = theCenter[1];
+ lon = theCenter[0];
+ alt = theCenter[2];
+ }
+
+ return (thePointList.size()>0);
+ }
+ virtual ossimPlanetKmlPoint* toPoint(){return this;}
+ virtual const ossimPlanetKmlPoint* toPoint()const{return this;}
+
+ virtual ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+
+ void setExtrudeFlag(bool flag)
+ {
+ theExtrudeFlag = flag;
+ }
+ bool extrudeFlag()const
+ {
+ return theExtrudeFlag;
+ }
+
+ void setTesselateFlag(bool flag)
+ {
+ theTesselateFlag = flag;
+ }
+ bool tesselateFlag()const
+ {
+ return theTesselateFlag;
+ }
+
+ const ossimPlanetKmlGeometry::PointListType& pointList()const
+ {
+ return thePointList;
+ }
+ ossimPlanetKmlGeometry::PointListType& pointList()
+ {
+ return thePointList;
+ }
+
+protected:
+ void clearFields()
+ {
+ theExtrudeFlag = false;
+ theTesselateFlag = false;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ thePointList.clear();
+ theCenter = osg::Vec3d(0.0,0.0,0.0);
+ }
+
+ bool theExtrudeFlag;
+ bool theTesselateFlag;
+ ossimPlanetAltitudeMode theAltitudeMode;
+ ossimPlanetKmlGeometry::PointListType thePointList;
+ osg::Vec3d theCenter;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLineString : public ossimPlanetKmlGeometry
+{
+public:
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual ossimPlanetKmlLineString* toLineString(){return this;}
+ virtual const ossimPlanetKmlLineString* toLineString()const{return this;}
+ virtual ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+
+ void setExtrudeFlag(bool flag)
+ {
+ theExtrudeFlag = flag;
+ }
+ bool extrudeFlag()const
+ {
+ return theExtrudeFlag;
+ }
+
+ void setTesselateFlag(bool flag)
+ {
+ theTesselateFlag = flag;
+ }
+ bool tesselateFlag()const
+ {
+ return theTesselateFlag;
+ }
+
+ const ossimPlanetKmlGeometry::PointListType& pointList()const
+ {
+ return thePointList;
+ }
+ ossimPlanetKmlGeometry::PointListType& pointList()
+ {
+ return thePointList;
+ }
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ if(thePointList.size() > 0)
+ {
+ lat = theCenter[1];
+ lon = theCenter[0];
+ alt = theCenter[2];
+ }
+
+ return (thePointList.size()>0);
+ }
+
+protected:
+ void clearFields()
+ {
+ theExtrudeFlag = false;
+ theTesselateFlag = false;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ thePointList.clear();
+ theCenter = osg::Vec3d(0.0,0.0,0.0);
+ }
+ bool theExtrudeFlag;
+ bool theTesselateFlag;
+ ossimPlanetAltitudeMode theAltitudeMode;
+ ossimPlanetKmlGeometry::PointListType thePointList;
+ osg::Vec3d theCenter;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLinearRing : public ossimPlanetKmlGeometry
+{
+public:
+ ossimPlanetKmlLinearRing()
+ :ossimPlanetKmlGeometry()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+
+ void setExtrudeFlag(bool flag)
+ {
+ theExtrudeFlag = flag;
+ }
+ bool extrudeFlag()const
+ {
+ return theExtrudeFlag;
+ }
+
+ void setTesselateFlag(bool flag)
+ {
+ theTesselateFlag = flag;
+ }
+ bool tesselateFlag()const
+ {
+ return theTesselateFlag;
+ }
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ if(thePointList.size() > 0)
+ {
+ lat = theCenter[1];
+ lon = theCenter[0];
+ alt = theCenter[2];
+ }
+
+ return (thePointList.size()>0);
+ }
+ virtual ossimPlanetKmlLinearRing* toLinearRing(){return this;}
+ virtual const ossimPlanetKmlLinearRing* toLinearRing()const{return this;}
+ const ossimPlanetKmlGeometry::PointListType& pointList()const
+ {
+ return thePointList;
+ }
+ ossimPlanetKmlGeometry::PointListType& pointList()
+ {
+ return thePointList;
+ }
+
+protected:
+ void clearFields()
+ {
+ theExtrudeFlag = false;
+ theTesselateFlag = false;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ thePointList.clear();
+ theCenter = osg::Vec3d(0.0,0.0,0.0);
+ }
+ bool theExtrudeFlag;
+ bool theTesselateFlag;
+ ossimPlanetAltitudeMode theAltitudeMode;
+ ossimPlanetKmlGeometry::PointListType thePointList;
+ osg::Vec3d theCenter;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlPolygon : public ossimPlanetKmlGeometry
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetKmlLinearRing> > InnerBoundaryList;
+
+ ossimPlanetKmlPolygon()
+ :ossimPlanetKmlGeometry()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+
+ void setExtrudeFlag(bool flag)
+ {
+ theExtrudeFlag = flag;
+ }
+ bool extrudeFlag()const
+ {
+ return theExtrudeFlag;
+ }
+
+ void setTesselateFlag(bool flag)
+ {
+ theTesselateFlag = flag;
+ }
+ bool tesselateFlag()const
+ {
+ return theTesselateFlag;
+ }
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ if(theOuterBoundary.valid())
+ {
+ return theOuterBoundary->getCenter(lat, lon, alt);
+ }
+
+ return false;
+ }
+ virtual ossimPlanetKmlPolygon* toPolygon(){return this;}
+ virtual const ossimPlanetKmlPolygon* toPolygon()const{return this;}
+
+
+ osg::ref_ptr<ossimPlanetKmlLinearRing> outerBoundary()
+ {
+ return theOuterBoundary;
+ }
+ const osg::ref_ptr<ossimPlanetKmlLinearRing> outerBoundary()const
+ {
+ return theOuterBoundary;
+ }
+
+ ossimPlanetKmlPolygon::InnerBoundaryList& innerBoundaryList()
+ {
+ return theInnerBoundaryList;
+ }
+
+ const ossimPlanetKmlPolygon::InnerBoundaryList& innerBoundaryList()const
+ {
+ return theInnerBoundaryList;
+ }
+
+protected:
+ void clearFields()
+ {
+ theExtrudeFlag = false;
+ theTesselateFlag = false;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ theOuterBoundary = 0;
+ theInnerBoundaryList.clear();
+ theCenter = osg::Vec3d(0.0,0.0,0.0);
+ }
+ bool theExtrudeFlag;
+ bool theTesselateFlag;
+ ossimPlanetAltitudeMode theAltitudeMode;
+ osg::ref_ptr<ossimPlanetKmlLinearRing> theOuterBoundary;
+ ossimPlanetKmlPolygon::InnerBoundaryList theInnerBoundaryList;
+ osg::Vec3d theCenter;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlMultiGeometry : public ossimPlanetKmlGeometry
+{
+public:
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ if(theGeometryList.size()>0)
+ {
+ theGeometryList[0]->getCenter(lat, lon, alt);
+ }
+/* if(theGeometryList.size() > 0) */
+/* { */
+/* double tempLat=0.0, tempLon=0.0, tempAlt=0.0; */
+/* theGeometryList[0]->getCenter(tempLat, tempLon, tempAlt); */
+/* ossim_uint32 idx = 1; */
+/* for(;idx < theGeometryList.size(); ++idx) */
+/* { */
+/* if(theGeometryList[idx]->getCenter(lat, lon, alt)) */
+/* { */
+/* tempLat += lat; */
+/* tempLon += lon; */
+/* tempAlt += alt; */
+/* } */
+/* } */
+/* lat = tempLat/(double)theGeometryList.size(); */
+/* lon = tempLon/(double)theGeometryList.size(); */
+/* alt = tempAlt/(double)theGeometryList.size(); */
+
+/* } */
+ return (theGeometryList.size() > 0);
+ }
+ virtual ossimPlanetKmlMultiGeometry* toMultiGeometry(){return this;}
+ virtual const ossimPlanetKmlMultiGeometry* toMultiGeometry()const{return this;}
+
+ std::vector<osg::ref_ptr<ossimPlanetKmlGeometry> >& geomtryList()
+ {
+ return theGeometryList;
+ }
+ const std::vector<osg::ref_ptr<ossimPlanetKmlGeometry> >& geomtryList()const
+ {
+ return theGeometryList;
+ }
+protected:
+ void clearFields()
+ {
+ theGeometryList.clear();
+ theCenter = osg::Vec3d(0.0,0.0,0.0);
+ }
+ std::vector<osg::ref_ptr<ossimPlanetKmlGeometry> > theGeometryList;
+ osg::Vec3d theCenter;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlModel : public ossimPlanetKmlGeometry
+{
+public:
+ ossimPlanetKmlModel()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ lat = theLocation->latitude();
+ lon = theLocation->longitude();
+ alt = theLocation->altitude();
+
+ return true;
+ }
+ virtual ossimPlanetKmlModel* toModel(){return this;}
+ virtual const ossimPlanetKmlModel* toModel()const{return this;}
+
+ osg::ref_ptr<ossimPlanetKmlLocation> location()
+ {
+ return theLocation;
+ }
+ const osg::ref_ptr<ossimPlanetKmlLocation> location()const
+ {
+ return theLocation;
+ }
+ osg::ref_ptr<ossimPlanetKmlOrientation> orientation()
+ {
+ return theOrientation;
+ }
+ const osg::ref_ptr<ossimPlanetKmlOrientation> orientation()const
+ {
+ return theOrientation;
+ }
+ osg::ref_ptr<ossimPlanetKmlScale> scale()
+ {
+ return theScale;
+ }
+
+ const osg::ref_ptr<ossimPlanetKmlScale> scale()const
+ {
+ return theScale;
+ }
+ osg::ref_ptr<ossimPlanetKmlLink> link()
+ {
+ return theLink;
+ }
+ const osg::ref_ptr<ossimPlanetKmlLink> link()const
+ {
+ return theLink;
+ }
+ virtual ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+ void setAltitudeMode(ossimPlanetAltitudeMode mode)
+ {
+ theAltitudeMode = mode;
+ }
+
+protected:
+ void clearFields()
+ {
+ theLocation = new ossimPlanetKmlLocation;
+ theOrientation = new ossimPlanetKmlOrientation;
+ theScale = new ossimPlanetKmlScale;
+ theLocation->setParent(this);
+ theOrientation->setParent(this);
+ theScale->setParent(this);
+ theLink = 0;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ }
+
+ osg::ref_ptr<ossimPlanetKmlLocation> theLocation;
+ osg::ref_ptr<ossimPlanetKmlOrientation> theOrientation;
+ osg::ref_ptr<ossimPlanetKmlScale> theScale;
+ osg::ref_ptr<ossimPlanetKmlLink> theLink;
+ ossimPlanetAltitudeMode theAltitudeMode;
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlOverlay : public ossimPlanetKmlFeature
+{
+public:
+ ossimPlanetKmlOverlay()
+ :ossimPlanetKmlFeature()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void setColor(const ossimString& value)
+ {
+ theColor = value;
+ }
+ const ossimString& color()const
+ {
+ return theColor;
+ }
+ void setDrawOrder(ossim_int32 value)
+ {
+ theDrawOrder = value;
+ }
+ ossim_int32 drawOrder()const
+ {
+ return theDrawOrder;
+ }
+ void clearFields()
+ {
+ theColor = "ffffffff";
+ theDrawOrder = 0;
+ theIcon = 0;
+ }
+ osg::ref_ptr<ossimPlanetKmlIcon> icon()
+ {
+ return theIcon;
+ }
+ const osg::ref_ptr<ossimPlanetKmlIcon> icon()const
+ {
+ return theIcon;
+ }
+
+protected:
+ ossimString theColor;
+ ossim_int32 theDrawOrder;
+ osg::ref_ptr<ossimPlanetKmlIcon> theIcon;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlScreenOverlay : public ossimPlanetKmlOverlay
+{
+public:
+ ossimPlanetKmlScreenOverlay()
+ :ossimPlanetKmlOverlay()
+ {
+ clearFields();
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ void setOverlayPosition(double x, double y)
+ {
+ theOverlayX = x;
+ theOverlayY = y;
+ }
+ void setOverlayUnits(ossimPlanetKmlUnits units)
+ {
+ theOverlayXUnits = units;
+ theOverlayYUnits = units;
+ }
+ void setOverlayXUnits(ossimPlanetKmlUnits units)
+ {
+ theOverlayXUnits = units;
+ }
+ void setOverlayYUnits(ossimPlanetKmlUnits units)
+ {
+ theOverlayYUnits = units;
+ }
+ double overlayX()const
+ {
+ return theOverlayX;
+ }
+ double overlayY()const
+ {
+ return theOverlayY;
+ }
+ ossimPlanetKmlUnits overlayXUnits()const
+ {
+ return theOverlayXUnits;
+ }
+ ossimPlanetKmlUnits overlayYUnits()const
+ {
+ return theOverlayYUnits;
+ }
+
+ void setScreenPosition(double x, double y)
+ {
+ theScreenX = x;
+ theScreenY = y;
+ }
+ void setScreenUnits(ossimPlanetKmlUnits units)
+ {
+ theScreenXUnits = units;
+ theScreenYUnits = units;
+ }
+ void setScreenXUnits(ossimPlanetKmlUnits units)
+ {
+ theScreenXUnits = units;
+ }
+ void setScreenYUnits(ossimPlanetKmlUnits units)
+ {
+ theScreenYUnits = units;
+ }
+ double screenX()const
+ {
+ return theScreenX;
+ }
+ double screenY()const
+ {
+ return theScreenY;
+ }
+ ossimPlanetKmlUnits screenXUnits()const
+ {
+ return theScreenXUnits;
+ }
+ ossimPlanetKmlUnits screenYUnits()const
+ {
+ return theScreenYUnits;
+ }
+ void setRotationXY(double xRotate, double yRotate)
+ {
+ theRotationX = xRotate;
+ theRotationY = yRotate;
+ }
+ void setRotationXYUnits(ossimPlanetKmlUnits units)
+ {
+ theRotationXUnits = units;
+ theRotationYUnits = units;
+ }
+ void setRotationXUnits(ossimPlanetKmlUnits units)
+ {
+ theRotationXUnits = units;
+ }
+ void setRotationYUnits(ossimPlanetKmlUnits units)
+ {
+ theRotationYUnits = units;
+ }
+ double rotationX()const
+ {
+ return theRotationX;
+ }
+ double rotationY()const
+ {
+ return theRotationY;
+ }
+
+ ossimPlanetKmlUnits rotationXUnits()const
+ {
+ return theRotationXUnits;
+ }
+ ossimPlanetKmlUnits rotationYUnits()const
+ {
+ return theRotationYUnits;
+ }
+ void setSize(double x, double y)
+ {
+ theSizeX = x;
+ theSizeY = y;
+ }
+ void setSizeX(double x)
+ {
+ theSizeX = x;
+ }
+ void setSizeY(double y)
+ {
+ theSizeY = y;
+ }
+ void setSizeUnits(ossimPlanetKmlUnits units)
+ {
+ theSizeXUnits = units;
+ theSizeYUnits = units;
+ }
+ double sizeX()const
+ {
+ return theSizeX;
+ }
+ double sizeY()const
+ {
+ return theSizeY;
+ }
+ ossimPlanetKmlUnits sizeXUnits()const
+ {
+ return theSizeXUnits;
+ }
+ ossimPlanetKmlUnits sizeYUnits()const
+ {
+ return theSizeYUnits;
+ }
+
+ void setRotation(float value)
+ {
+ theRotation = value;
+ }
+ float rotation()const
+ {
+ return theRotation;
+ }
+ void clearFields()
+ {
+ theOverlayX= 0.0;
+ theOverlayY= 0.0;
+ theOverlayXUnits = ossimPlanetKmlUnits_FRACTION;
+ theOverlayYUnits = ossimPlanetKmlUnits_FRACTION;
+ theScreenX= 0.0;
+ theScreenY= 0.0;
+ theScreenXUnits = ossimPlanetKmlUnits_FRACTION;
+ theScreenYUnits = ossimPlanetKmlUnits_FRACTION;
+ theRotationX = 0.0;
+ theRotationY = 0.0;
+ theRotationXUnits = ossimPlanetKmlUnits_FRACTION;
+ theRotationYUnits = ossimPlanetKmlUnits_FRACTION;
+ theSizeX = 0.0;
+ theSizeY = 0.0;
+ theSizeXUnits = ossimPlanetKmlUnits_FRACTION;
+ theSizeYUnits = ossimPlanetKmlUnits_FRACTION;
+ theRotation = 0.0;
+ }
+
+protected:
+ double theOverlayX;
+ double theOverlayY;
+ ossimPlanetKmlUnits theOverlayXUnits;
+ ossimPlanetKmlUnits theOverlayYUnits;
+ double theScreenX;
+ double theScreenY;
+ ossimPlanetKmlUnits theScreenXUnits;
+ ossimPlanetKmlUnits theScreenYUnits;
+ double theRotationX;
+ double theRotationY;
+ ossimPlanetKmlUnits theRotationXUnits;
+ ossimPlanetKmlUnits theRotationYUnits;
+ double theSizeX;
+ double theSizeY;
+ ossimPlanetKmlUnits theSizeXUnits;
+ ossimPlanetKmlUnits theSizeYUnits;
+ float theRotation;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlGroundOverlay : public ossimPlanetKmlOverlay
+{
+public:
+ ossimPlanetKmlGroundOverlay()
+ :ossimPlanetKmlOverlay(),
+ theAltitude(0.0),
+ theAltitudeMode(ossimPlanetAltitudeMode_CLAMP_TO_GROUND),
+ theLatLonBox(0)
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ double altitude()const
+ {
+ return theAltitude;
+ }
+ void setAltitude(double value)
+ {
+ theAltitude = value;
+ }
+ ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theAltitudeMode;
+ }
+ void setAltitudeMode(ossimPlanetAltitudeMode mode)
+ {
+ theAltitudeMode = mode;
+ }
+ const osg::ref_ptr<ossimPlanetKmlLatLonBox> latLonBox()const
+ {
+ return theLatLonBox;
+ }
+ void setLatLonBox(osg::ref_ptr<ossimPlanetKmlLatLonBox> value)
+ {
+ theLatLonBox = value;
+ }
+ void clearFields()
+ {
+ theAltitude = 0.0;
+ theAltitudeMode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ theLatLonBox = 0;
+ }
+protected:
+ double theAltitude;
+ ossimPlanetAltitudeMode theAltitudeMode;
+ osg::ref_ptr<ossimPlanetKmlLatLonBox> theLatLonBox;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlNetworkLink : public ossimPlanetKmlFeature
+{
+public:
+ ossimPlanetKmlNetworkLink()
+ :ossimPlanetKmlFeature()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ const ossimPlanetKmlLink* link()const
+ {
+ return theLink.get();
+ }
+ ossimPlanetKmlLink* link()
+ {
+ return theLink.get();
+ }
+ void setLink(osg::ref_ptr<ossimPlanetKmlLink> value)
+ {
+ theLink = value;
+ }
+ bool refreshVisibilityFlag()const
+ {
+ return theRefreshVisibilityFlag;
+ }
+ void setRefreshVisibilityFlag(bool value)
+ {
+ theRefreshVisibilityFlag = value;
+ }
+ bool flyToViewFlag()const
+ {
+ return theFlyToViewFlag;
+ }
+ void setFlyToViewFlag(bool value)
+ {
+ theFlyToViewFlag = value;
+ }
+ void clearFields()
+ {
+ theLink = 0;
+ theRefreshVisibilityFlag = false;
+ theFlyToViewFlag = false;
+ }
+
+protected:
+
+ osg::ref_ptr<ossimPlanetKmlLink> theLink;
+
+ bool theRefreshVisibilityFlag;
+ bool theFlyToViewFlag;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlPlacemark : public ossimPlanetKmlFeature
+{
+public:
+ ossimPlanetKmlPlacemark()
+ :ossimPlanetKmlFeature()
+ {}
+ bool parse(const ossimRefPtr<ossimXmlNode> node);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+ void clearFields()
+ {
+ theGeometry = 0;
+ }
+ osg::ref_ptr<ossimPlanetKmlGeometry> getGeometry()
+ {
+ return theGeometry;
+ }
+ const osg::ref_ptr<ossimPlanetKmlGeometry> getGeometry()const
+ {
+ return theGeometry;
+ }
+ virtual bool getCenter(double& lat, double& lon, double& alt)const
+ {
+ bool result = ossimPlanetKmlFeature::getCenter(lat, lon, alt);
+
+ if(!result)
+ {
+ if(theGeometry.valid())
+ {
+ result = theGeometry->getCenter(lat, lon, alt);
+ }
+ }
+ return result;
+ }
+
+ void setColor(std::string color)
+ {
+ thePColor = color;
+ }
+ const std::string& getPColor()const
+ {
+ return thePColor;
+ }
+
+protected:
+ std::string thePColor;
+ osg::ref_ptr<ossimPlanetKmlGeometry> theGeometry;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlContainer : public ossimPlanetKmlFeature
+{
+public:
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlFolder : public ossimPlanetKmlContainer
+{
+public:
+ ossimPlanetKmlFolder()
+ :ossimPlanetKmlContainer()
+ {
+ }
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> xmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlDocument : public ossimPlanetKmlContainer
+{
+public:
+ ossimPlanetKmlDocument();
+ bool parse(const ossimRefPtr<ossimXmlNode> node);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+};
+
+class OSSIMPLANET_DLL ossimPlanetKml : public ossimPlanetKmlObject
+{
+public:
+ typedef std::map<std::string, osg::ref_ptr<ossimPlanetKmlObject> > IdMapType;
+ ossimPlanetKml();
+
+ virtual bool parse(const ossimFilename& file);
+ virtual bool parse(std::istream& in, bool fullDocumentFlag=true);
+ virtual bool parse(const ossimRefPtr<ossimXmlDocument> document);
+
+/* const ossimPlanetKmlObject::ObjectList& getObjectList()const */
+/* { */
+/* return theObjectList; */
+/* } */
+
+ virtual bool parse(const ossimRefPtr<ossimXmlNode> kmlNode);
+ virtual void write(ossimRefPtr<ossimXmlNode> xmlNode)const;
+ virtual ossimRefPtr<ossimXmlDocument> writeDocument()const;
+ bool getAllFeatures(ossimPlanetKmlObject::ObjectList& placemarks);
+ void createIdMap()const;
+ osg::ref_ptr<ossimPlanetKmlObject> findById(const ossimString& id);
+ const osg::ref_ptr<ossimPlanetKmlObject> findById(const ossimString& id)const;
+
+ const ossimFilename& filename()const
+ {
+ return theFilename;
+ }
+ virtual bool isCompressed()const
+ {
+ return false;
+ }
+
+ ossimFilename getCacheLocation(bool sharedLocationFlag = false)const;
+ virtual ossimFilename getKmlFile()const
+ {
+ return theFilename;
+ }
+protected:
+ ossimFilename theFilename;
+ mutable ossimFilename theCacheLocation;
+ mutable bool theIdMapGeneratedFlag;
+ mutable IdMapType theIdMap;
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetKmz : public ossimPlanetKml
+{
+public:
+
+ ossimPlanetKmz();
+ virtual ~ossimPlanetKmz();
+ virtual bool parse(std::istream& in);
+ virtual bool parse(const ossimFilename& file);
+ virtual bool isCompressed()const
+ {
+ return true;
+ }
+protected:
+ void extractFiles();
+ void deleteExtractedFiles();
+ void* thePrivateData;
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetKmlObjectRegistry
+{
+public:
+ static ossimPlanetKmlObjectRegistry* instance();
+ ossimPlanetKmlObject* newObject(const ossimXmlNode* tag)const;
+ ossimPlanetKmlObject* newObject(const ossimString& tag)const;
+ ossimPlanetKmlObject* newGeometry(const ossimString& tag)const;
+ ossimPlanetKmlObject* newTimePrimitive(const ossimString& tag)const;
+ ossimPlanetKmlObject* newColorStyle(const ossimString& tag)const;
+
+protected:
+ ossimPlanetKmlObjectRegistry();
+ ossimPlanetKmlObjectRegistry(const ossimPlanetKmlObjectRegistry&){}
+
+ static ossimPlanetKmlObjectRegistry* theInstance;
+
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKmlLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlLayer.h
new file mode 100644
index 0000000..d0d0be6
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlLayer.h
@@ -0,0 +1,201 @@
+#ifndef ossimPlanetKmlLayer_HEADER
+#define ossimPlanetKmlLayer_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetKmlLayerNode.h>
+#include <ossimPlanet/ossimPlanetKml.h>
+#include <OpenThreads/Mutex>
+#include <osgDB/ReaderWriter>
+#include <osg/Texture2D>
+#include <osg/FrameStamp>
+#include <osgUtil/IntersectVisitor>
+#include <queue>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <time.h>
+#include <ossimPlanet/ossimPlanetIconGeom.h>
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+
+class ossimPlanet;
+class OSSIMPLANET_DLL ossimPlanetKmlLayerReaderWriter : public osgDB::ReaderWriter
+{
+public:
+ ossimPlanetKmlLayerReaderWriter(ossimPlanetKmlLayer* layer=0)
+ :theLayer(layer)
+ {
+ theRecurseFlag = false;
+ srand(time(0));
+ }
+ void setLayer(ossimPlanetKmlLayer* layer)
+ {
+ theLayer = layer;
+ }
+ virtual ReadResult readNode(const std::string& fileName, const Options*)const;
+ void setKmlCacheLocation(const ossimFilename& location)
+ {
+ theKmlCacheLocation = location;
+ }
+ virtual ReadResult readImage(const std::string& /*fileName*/,const Options* =NULL) const;
+ void setId(const ossimString& id)
+ {
+ theIdString = id;
+ }
+protected:
+
+ mutable ossimPlanetKmlLayer* theLayer;
+ ossimFilename theKmlCacheLocation;
+ mutable ossimFilename theCurrentPlwLocation;
+ mutable bool theRecurseFlag;
+ ossimString theIdString;
+};
+
+
+
+// theis is teporary testing for ground annotations. We will initially be testing
+// grouping of Placemark Icons into common/shared draws
+//
+class ossimPlanetKmlLayerTile : public osg::Referenced
+{
+public:
+
+protected:
+ // will hold the tile location
+ ossim_uint32 theRow;
+ ossim_uint32 theCol;
+ ossim_uint32 theLevel;
+ ossim_uint32 theFace;
+
+ // will hold the local space transform for this cell.
+ // used to convert common points to the local space.
+ // Entities will be added to this graph after transformation
+ //
+ osg::ref_ptr<osg::MatrixTransform> theLocalToWorldTransform;
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetKmlLayer : public ossimPlanetLayer
+{
+ friend class ossimPlanetKmlLayerReaderWriter;
+public:
+ class FindNodeVisitor : public osg::NodeVisitor
+ {
+ public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetKmlLayerNode> > LayerNodeList;
+ FindNodeVisitor(const ossimString& id)
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ theId(id)
+ {
+ }
+ virtual void apply(osg::Node& node)
+ {
+ ossimPlanetKmlLayerNode* n = dynamic_cast<ossimPlanetKmlLayerNode*>(&node);
+ if(n)
+ {
+ if(n->id() == theId)
+ {
+ theLayerNodeList.push_back(n);
+ }
+ }
+
+ traverse(node);
+ }
+ FindNodeVisitor::LayerNodeList& layerList()
+ {
+ return theLayerNodeList;
+ }
+ const FindNodeVisitor::LayerNodeList& layerList()const
+ {
+ return theLayerNodeList;
+ }
+
+ protected:
+ FindNodeVisitor::LayerNodeList theLayerNodeList;
+ ossimString theId;
+ };
+ typedef std::map<std::string, osg::ref_ptr<ossimPlanetIconGeom> > IconMap;
+ class OSSIMPLANET_DLL ossimPlanetKmlLayerCallback : public osg::Referenced
+ {
+ public:
+ ossimPlanetKmlLayerCallback()
+ :osg::Referenced(),
+ theEnableFlag(true)
+ {
+ }
+ virtual void nodeAdded(osg::Node* /*node*/){}
+ virtual void nodeDeleted(osg::Node* /*node*/){}
+ bool enableFlag()const
+ {
+ return theEnableFlag;
+ }
+ void setEnableFlag(bool flag)
+ {
+ theEnableFlag = flag;
+ }
+ protected:
+ bool theEnableFlag;
+ };
+ ossimPlanetKmlLayer();
+ virtual osg::Object* cloneType() const { return new ossimPlanetKmlLayer(); }
+ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ossimPlanetKmlLayer *>(obj)!=0; }
+ virtual const char* className() const { return "ossimPlanetKmlLayer"; }
+ virtual const char* libraryName() const { return "ossimPlanet"; }
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual void addKml(const ossimFilename& kmlFile);
+ virtual void addKml(osg::ref_ptr<ossimPlanetKmlObject> kml);
+ virtual void addKml(osg::ref_ptr<osg::Group> parent,
+ osg::ref_ptr<ossimPlanetKmlObject> kml);
+
+ virtual bool addChild( Node *child );
+
+ osg::ref_ptr<ossimPlanetIconGeom> getOrCreateIconEntry(const ossimString& src);
+ osg::ref_ptr<ossimPlanetIconGeom> getIconEntry(const ossimString& src);
+ void deleteNode(const ossimString& id);
+
+ const ossimPlanet* planet()const;
+ const ossimPlanetGeoRefModel* landModel()const;
+ ossimPlanet* planet();
+ ossimPlanetGeoRefModel* landModel();
+
+ void readyToAddNode(osg::Group* parent,
+ osg::Node* node);
+
+protected:
+
+ class NodeToAddInfo
+ {
+ public:
+ NodeToAddInfo(osg::Group* parent,
+ osg::Node* node)
+ :theParent(parent),
+ theNode(node)
+ {
+ }
+ osg::ref_ptr<osg::Group> theParent;
+ osg::ref_ptr<osg::Node> theNode;
+ };
+ bool hasCallback(const ossimPlanetKmlLayerCallback* callback)const;
+ void initializePalettes();
+ mutable ossimPlanetReentrantMutex theGraphMutex;
+ mutable ossimPlanetReentrantMutex theReadyToAddListMutex;
+ mutable ossimPlanetReentrantMutex theReadyToProcessKmlListMutex;
+ std::vector<osg::ref_ptr<ossimPlanetKmlLayerNode> > theNodeList;
+
+
+ std::queue<ossimFilename> theReadyToProcessKmlFileList;
+ std::queue<osg::ref_ptr<ossimPlanetKmlObject> > theReadyToProcessKmlList;
+ osg::ref_ptr<ossimPlanetKmlLayerReaderWriter> theReaderWriter;
+ ossimFilename theKmlCacheLocation;
+ ossimPlanetKmlLayer::IconMap theIconMap;
+ osg::ref_ptr<osg::FrameStamp> theFudgeStamp;
+// osg::ref_ptr<ossimPlanetDatabasePager> theDatabasePager;
+ bool theNodesAddedFlag;
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> theOperationQueue;
+// osg::ref_ptr<ossimPlanetKmlLayer::PagerCallback> thePagerCallback;
+
+ OpenThreads::Mutex theNodesToAddListMutex;
+ std::vector<NodeToAddInfo> theNodesToAddList;
+ osg::ref_ptr<osg::Referenced> theRequestRef;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKmlLayerNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlLayerNode.h
new file mode 100644
index 0000000..d6fe33b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlLayerNode.h
@@ -0,0 +1,49 @@
+#ifndef ossimPlanetKmlLayerNode_HEADER
+#define ossimPlanetKmlLayerNode_HEADER
+#include <osg/Group>
+#include <ossimPlanet/ossimPlanetKml.h>
+#include <ossimPlanet/ossimPlanetNode.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <osg/Image>
+class ossimPlanetKmlLayer;
+
+class OSSIMPLANET_DLL ossimPlanetKmlLayerNode : public ossimPlanetNode
+{
+public:
+ ossimPlanetKmlLayerNode(ossimPlanetKmlLayer* layer = 0,
+ ossimPlanetKmlObject* obj = 0);
+ void setKmlLayer(ossimPlanetKmlLayer* layer)
+ {
+ theLayer = layer;
+ }
+ void setLayer(ossimPlanetKmlLayer* layer);
+ void setKmlObject(ossimPlanetKmlObject* obj);
+ ossimPlanetKmlLayer* layer();
+
+ osg::ref_ptr<ossimPlanetKmlObject> kmlObject()
+ {
+ return theKmlObject.get();
+ }
+
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ /**
+ * This is a convenient method for interactive GUIs to call to allow a KML node to change its state
+ * in the scene graph.
+ */
+ virtual void doNormalStyle(){}
+
+ /**
+ * This is a convenient method for interactive GUIs to call to allow the KML node to change its state
+ * in the scene graph.
+ */
+ virtual void doHighlightStyle(){}
+
+ virtual bool init();
+
+protected:
+ ossimPlanetKmlLayer* theLayer;
+ osg::ref_ptr<ossimPlanetKmlObject> theKmlObject;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKmlNetworkLinkNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlNetworkLinkNode.h
new file mode 100644
index 0000000..91ab760
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlNetworkLinkNode.h
@@ -0,0 +1,18 @@
+#ifndef ossimPlanetKmlNetworkLinkNode_HEADER
+#define ossimPlanetKmlNetworkLinkNode_HEADER
+#include <ossimPlanet/ossimPlanetKmlLayerNode.h>
+
+class OSSIMPLANET_DLL ossimPlanetKmlNetworkLinkNode : public ossimPlanetKmlLayerNode
+{
+public:
+ ossimPlanetKmlNetworkLinkNode(ossimPlanetKmlLayer* layer = 0,
+ ossimPlanetKmlObject* obj = 0);
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual bool init();
+
+protected:
+ osg::ref_ptr<ossimPlanetKml> theKmlData;
+ bool theScheduledFlag;
+
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKmlPlacemarkNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlPlacemarkNode.h
new file mode 100644
index 0000000..55c9aae
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlPlacemarkNode.h
@@ -0,0 +1,72 @@
+#ifndef ossimPlanetKmlPlacemarkNode_HEADER
+#define ossimPlanetKmlPlacemarkNode_HEADER
+#include <ossimPlanet/ossimPlanetKmlLayerNode.h>
+#include <ossimPlanet/ossimPlanetLabelGeom.h>
+#include <osg/MatrixTransform>
+#include <ossimPlanet/ossimPlanetBillboardIcon.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetFadeText.h>
+#include <osg/ClusterCullingCallback>
+#include <ossimPlanet/ossimPlanetKml.h>
+
+class ossimPlanetKmlPlacemarkNode : public ossimPlanetKmlLayerNode
+{
+public:
+ ossimPlanetKmlPlacemarkNode(ossimPlanetKmlLayer* layer = 0,
+ ossimPlanetKmlObject* obj = 0);
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ virtual bool init();
+
+protected:
+ class PlacemarkGeometryDraw : public osg::Drawable::DrawCallback
+ {
+ public:
+ PlacemarkGeometryDraw()
+ :theOpacity(1.0)
+ {
+
+ }
+ virtual void drawImplementation(osg::RenderInfo& /*renderInfo*/,
+ const osg::Drawable* /*drawable*/)const;
+ public:
+ float theOpacity;
+ };
+ double convertHeight(const osg::Vec3d& kmlWorldPoint,
+ ossimPlanetAltitudeMode altMode,
+ ossimPlanetGeoRefModel* landModel)const;
+
+ void convertPointsToLocalCoordinates(osg::Vec3Array* result,
+ const ossimPlanetKmlGeometry::PointListType& pointList,
+ const osg::Matrixd& worldToLocalTransform,
+ ossimPlanetGeoRefModel* landModel,
+ ossimPlanetAltitudeMode altMode,
+ double& minHeight,
+ double& maxHeight)const;
+
+ void extrude(osg::ref_ptr<osg::Geometry> result,
+ osg::Vec3Array* verts,
+ osg::Vec3Array* extrusionVerts,
+ const std::vector<std::pair<ossim_uint32, ossim_uint32> >& extrusionGroups)const;
+
+
+
+ double theNormalizationScale;
+ osg::ref_ptr<osg::Group> theKmlGeometries;
+ osg::ref_ptr<osg::Group> theKmlPickableGeometries;
+ bool theCulledFlag;
+
+ // we will shift the center of the bounds to the ground level
+ // and use this for determining pixel coverage
+ //
+ ossim_float64 theRadius;
+ osg::Vec3d theCenter;
+
+ ossim_float32 theFadeAlpha;
+ osg::ref_ptr<PlacemarkGeometryDraw> theDraw;
+ osg::ref_ptr<ossimPlanetKmlRegion> theRegion;
+ osg::ref_ptr<ossimPlanetKmlLod> theLod;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKmlReaderWriter.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlReaderWriter.h
new file mode 100644
index 0000000..4c2c8c0
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlReaderWriter.h
@@ -0,0 +1,16 @@
+#ifndef ossimPlanetKmlReaderWriter_HEADER
+#define ossimPlanetKmlReaderWriter_HEADER
+#include <osgDB/ReaderWriter>
+
+class ossimPlanetKmlReaderWriter : : public osgDB::ReaderWriter
+{
+public:
+ ossimPlanetKmlReaderWriter();
+
+ virtual ReadResult readNode(const std::string& /*fileName*/, const Options* =NULL) const;
+
+protected:
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetKmlScreenOverlayNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlScreenOverlayNode.h
new file mode 100644
index 0000000..14a2be2
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetKmlScreenOverlayNode.h
@@ -0,0 +1,49 @@
+#ifndef ossimPlanetKmlScreenOverlayNode_HEADER
+#define ossimPlanetKmlScreenOverlayNode_HEADER
+#include <ossimPlanet/ossimPlanetKml.h>
+#include <ossimPlanet/ossimPlanetKmlLayerNode.h>
+#include <osg/Group>
+#include <osg/CameraNode>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetIconGeom.h>
+
+class ossimPlanetKmlScreenOverlayNode : public ossimPlanetKmlLayerNode
+{
+public:
+ ossimPlanetKmlScreenOverlayNode(ossimPlanetKmlLayer* layer = 0,
+ ossimPlanetKmlObject* obj = 0);
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual bool init();
+
+protected:
+ void update();
+ void computeOverlayXY(osg::Vec3d& position);
+ void computeScreenXY(osg::Vec3d& position);
+ void computeSize(osg::Vec3d& size);
+
+ osg::ref_ptr<osg::CameraNode> theCameraNode;
+ osg::ref_ptr<osg::Group> theGroup;
+ osg::ref_ptr<osg::Viewport> theViewport;
+ osg::ref_ptr<osg::Geode> theIconGeode;
+ osg::ref_ptr<ossimPlanetIconGeom> theIconGeom;
+ bool theViewportChangedFlag;
+ bool theNeedsUpdateFlag;
+
+ osg::Vec2d theOverlayOrigin;
+ ossimPlanetKmlUnits theOverlayXUnits;
+ ossimPlanetKmlUnits theOverlayYUnits;
+ osg::Vec2d theScreenOrigin;
+ ossimPlanetKmlUnits theScreenXUnits;
+ ossimPlanetKmlUnits theScreenYUnits;
+
+ osg::Vec2d theRotationOrigin;
+ ossimPlanetKmlUnits theRotationXUnits;
+ ossimPlanetKmlUnits theRotationYUnits;
+ osg::Vec2d theSize;
+ ossimPlanetKmlUnits theSizeXUnits;
+ ossimPlanetKmlUnits theSizeYUnits;
+ float theRotation;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLabelGeom.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLabelGeom.h
new file mode 100644
index 0000000..4a08365
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLabelGeom.h
@@ -0,0 +1,77 @@
+#ifndef ossimPlanetLabelGeom_HEADER
+#define ossimPlanetLabelGeom_HEADER
+#include <osg/Node>
+#include <osg/CoordinateSystemNode>
+#include <osg/MatrixTransform>
+#include <osg/Billboard>
+#include <osgText/Text>
+#include <osg/Matrixd>
+#include <osg/Vec4f>
+#include <ossim/base/ossimString.h>
+
+class ossimPlanetLabelGeom : public osg::Node
+{
+public:
+ enum ShowState
+ {
+ SHOW_NO_STATE = 0,
+ SHOW_WHEN_FULL_RES = 1, // default
+ SHOW_ALWAYS = 2
+ };
+ class ossimPlanetLabelGeomUpdateCallback : public osg::NodeCallback
+ {
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ ossimPlanetLabelGeom* n = dynamic_cast<ossimPlanetLabelGeom*>(node);
+ if(n)
+ {
+ n->traverse(*nv);
+ }
+ }
+ };
+ ossimPlanetLabelGeom(const ossimString& label="",
+ double characterSizeInObjectSpace=1.0/osg::WGS_84_RADIUS_EQUATOR);
+ virtual ~ossimPlanetLabelGeom();
+ void setAlignment(osgText::Text::AlignmentType alignment);
+ void setCharacterSizeInObjectSpace(double objectSize);
+ osg::ref_ptr<osgText::Text> getLabel();
+ void setLabel(const ossimString& label);
+ /**
+ * Setting to 0 or negative says there is no max height.
+ */
+ void setMaxHeightInPixels(double pixelHeight);
+ /**
+ * Setting to 0 or negative value says there is no minimum height.
+ */
+ void setMinHeightInPixels(double pixelHeight);
+
+ void setColor(float r, float g, float b, float a=1.0);
+ void setEnableFlag(bool enableFlag);
+ void setShowFlag(bool show);
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual osg::BoundingSphere computeBound() const;
+protected:
+ /**
+ * Specifies how the label should be shown. You can show it once it reaches full resolution of the pixel
+ * identified by the .
+ */
+ ossimPlanetLabelGeom::ShowState theShowState;
+ mutable bool theShowFlag;
+ mutable bool theUpdateTransformFlag;
+ bool theEnableFlag;
+ double theMaxHeightInPixels;
+ double theMinHeightInPixels;
+
+ /**
+ * used to make sure the font is at desired size in pixel if the
+ * max or min font heights are specified.
+ */
+ osg::ref_ptr<osg::MatrixTransform> theTransform;
+ osg::ref_ptr<osg::Billboard> theBillboard;
+ osg::ref_ptr<osgText::Text> theLabel;
+ osg::Matrixd theMatrix;
+ osg::Vec4f theColor;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLand.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLand.h
new file mode 100644
index 0000000..244a41f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLand.h
@@ -0,0 +1,181 @@
+#ifndef ossimPlanetLand_HEADER
+#define ossimPlanetLand_HEADER
+#include <osg/Group>
+#include <osg/Timer>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <osgDB/DatabasePager>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossimPlanet/ossimPlanetLandNormalType.h>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetExtents.h>
+#include <ossimPlanet/ossimPlanetShaderProgramSetup.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossimPlanet/ossimPlanetLandCache.h>
+#include <ossimPlanet/ossimPlanetElevationDatabaseGroup.h>
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetLandCullCallback.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <osg/GL2Extensions>
+
+class ossimPlanetGeoRefModel;
+class ossimPlanetLandReaderWriter;
+
+class OSSIMPLANET_DLL ossimPlanetLand : public ossimPlanetLayer
+{
+public:
+ friend class ossimPlanetLandUpdateCallback;
+ friend class ossimPlanetLandRefreshVisitor;
+ ossimPlanetLand();
+
+ virtual osg::Object* cloneType() const { return new ossimPlanetLand(); }
+ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ossimPlanetLand *>(obj)!=NULL; }
+ virtual const char* className() const { return "ossimPlanetLand"; }
+ virtual const char* libraryName() const { return "ossimPlanet"; }
+ virtual void accept(osg::NodeVisitor& nv);
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ virtual void setModel(ossimPlanetGeoRefModel* model);
+ void setLineOfSiteIntersection(const osg::Vec3d& pt);
+
+ void setElevationEnabledFlag(bool elevationEnabledFlag);
+ bool getElevationEnabledFlag()const;
+
+ ossim_float64 getHeightExag()const;
+ void setHeightExag(ossim_float64 heightExag);
+ ossim_uint32 getElevationPatchSize()const;
+ void setElevationPatchSize(ossim_uint32 patchSize);
+ void setReaderWriter(ossimPlanetLandReaderWriter* readerWriter);
+ ossimPlanetLandReaderWriter* getReaderWriter();
+ const ossimPlanetLandReaderWriter* getReaderWriter()const;
+ ossim_uint32 getMaxLevelDetail()const;
+ void setMaxLevelDetail(ossim_uint32 maxLevelDetail);
+ ossimFilename getElevationCacheDir()const;
+ void setElevationCacheDir(const ossimFilename& cacheDir);
+ void resetGraph(osg::ref_ptr<ossimPlanetExtents> extents=0,
+ ossimPlanetLandRefreshType refreshType=ossimPlanetLandRefreshType_PRUNE);
+ virtual bool addChild( Node *child );
+ const osg::ref_ptr<ossimPlanetGeoRefModel> model()const;
+
+ ossim_uint32 getNumberOfOverlayLayers()const;
+ void setReferenceLayer(osg::ref_ptr<ossimPlanetTextureLayerGroup> reference);
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> referenceLayer();
+ const osg::ref_ptr<ossimPlanetTextureLayerGroup> referenceLayer()const;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> overlayLayers();
+ const osg::ref_ptr<ossimPlanetTextureLayerGroup> overlayLayers()const;
+ osg::ref_ptr<ossimPlanetTextureLayer> overlayLayer(ossim_uint32 layerIdx);
+ const osg::ref_ptr<ossimPlanetTextureLayer> overlayLayer(ossim_uint32 layerIdx)const;
+ osg::ref_ptr<ossimPlanetTextureLayer> removeOverlayLayer(ossim_uint32 layerIdx);
+ void addOverlayLayer(osg::ref_ptr<ossimPlanetTextureLayerGroup> overlay);
+ void setOverlayLayer(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> overlay);
+ osg::ref_ptr<ossimPlanetShaderProgramSetup> getCurrentShader();
+ void setCurrentFragmentShaderType(ossimPlanetShaderProgramSetup::ossimPlanetFragmentShaderType fragType);
+ /**
+ * Setting to 0 will disable caching. The second argument dictates how far to shrink the cache when it exceeds
+ * the maxSize allowed. Maybe a good value is .85*maxSize. This will allow about a 15% reduction in cache size
+ */
+ void setCacheSize(ossim_uint64 maxSize, ossim_uint64 minSize);
+ ossim_uint64 getCacheSize()const;
+
+ /**
+ * This is a ratio distance from the eye versus to radial bounds of
+ * a patch. By default this is set to 3. So this means that once the eye
+ * is within 3 times the radial distance of the patch the patch will split. So the affect is
+ * increasing this number will cause the land to tesselate faster as the eye approaches.
+ */
+ void setSplitMetricRatio(double ratio);
+ double getSplitMetricRatio()const;
+
+ void setSplitPriorityType(ossimPlanetPriorityType priorityType);
+ ossimPlanetPriorityType getSplitPrioirtyType()const;
+
+ void setCullingFlag(bool flag);
+ bool getCullingFlag()const;
+
+ void setFreezeRequestFlag(bool flag);
+ bool getFreezRequestFlag()const;
+
+ bool getMipMappingFlag()const;
+ void setMipMappingFlag(bool flag);
+
+ void addElevationDirectory(const ossimFilename& file, bool sortFlag=false);
+ void addElevation(osg::ref_ptr<ossimPlanetElevationDatabase> database, bool sortFlag=false);
+ bool shadersInitialized()const;
+
+ void clearElevation();
+
+
+ /**
+ * Will add callbacks to the textures layers and automatically refresh the scene graph as needed if the passed in
+ * flag is true. If you want to control refreshing then set the flag to false.
+ */
+/* void setAutoRefreshFlag(bool flag); */
+/* bool getAutoRefreshFlag(bool flag)const; */
+
+ void pagedLodAdded(osg::Node* parent, osg::Node* child);
+ void pagedLodRemoved(osg::Node* node);
+ void pagedLodModified(osg::Node* node);
+
+ /**
+ * Executes receiver command actions:
+ * <pre>
+ *
+ * </pre>
+ */
+ virtual void execute(const ossimPlanetAction &a);
+
+protected:
+ struct refreshInfo : public osg::Referenced
+ {
+ osg::ref_ptr<ossimPlanetExtents> theExtents;
+ ossimPlanetLandRefreshType theRefreshType;
+ };
+ virtual ~ossimPlanetLand();
+ void xmlExecute(const ossimPlanetXmlAction& a);
+ void resetGraphLocal();
+ void initShaders();
+ void initElevation();
+
+ void add(const ossimPlanetAction& a);
+ void remove(const ossimPlanetAction& a);
+ void resetGraph(const ossimPlanetAction& a);
+ void addImageObject(const ossimString& objectName, const ossimString& objectArg);
+
+ osg::ref_ptr<ossimPlanetLandReaderWriter> theReaderWriter;
+ static ossim_uint32 theLandReaderWriterId;
+ mutable ossimPlanetReentrantMutex theMutex;
+ mutable ossimPlanetReentrantMutex theRefreshMutex;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> theReferenceLayer;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> theOverlayLayers;
+ mutable std::vector<osg::ref_ptr<refreshInfo> > theExtentRefreshList;
+ osg::ref_ptr<ossimPlanetShaderProgramSetup> theCurrentShaderProgram;
+ osg::ref_ptr<osg::Uniform> theReferenceTexture;
+ osg::ref_ptr<osg::Uniform> theTopTexture;
+ osg::ref_ptr<osg::Program> theLandShaderProgram;
+ osg::ref_ptr<osg::Program> theNoShaderProgram;
+ osg::ref_ptr<osg::Shader> theVertexShader;
+ osg::ref_ptr<osg::Shader> theFragShader;
+ std::string theTopSource;
+ std::string theReferenceSource;
+ std::string theOpacitySource;
+ std::string theSwipeSource;
+ std::string theFalseColorReplacementSource;
+ std::string theAbsoluteDifferenceSource;
+ bool theAutoRefreshFlag;
+ osg::ref_ptr<osg::StateSet> theStateSet;
+ osg::ref_ptr<osg::GL2Extensions> theGL2Extensions;
+ osg::ref_ptr<ossimPlanetLandCache> theLandCache;
+ osg::ref_ptr<ossimPlanetElevationDatabaseGroup> theElevationDatabase;
+ osg::ref_ptr<ossimPlanetLandCullCallback> theCullCallback;
+ osg::ref_ptr<ossimPlanetTextureLayerCallback> theTextureLayerCallback;
+ osg::ref_ptr<ossimPlanetTextureLayerCallback> theElevationLayerCallback;
+
+ bool theShadersInitializedFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandCache.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandCache.h
new file mode 100644
index 0000000..7cab3bd
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandCache.h
@@ -0,0 +1,114 @@
+#ifndef ossimPlanetLandCache_HEADER
+#define ossimPlanetLandCache_HEADER
+
+#include <osg/Timer>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetExtents.h>
+#include <osg/Referenced>
+#include <osg/Geometry>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class ossimPlanetLandCache;
+class OSSIMPLANET_DLL ossimPlanetLandCacheNode : public osg::Referenced
+{
+public:
+ friend class ossimPlanetLandCache;
+ ossimPlanetLandCacheNode(ossimPlanetLandCache* landCache=0,
+ ossim_uint64 id=0)
+ :theTimeStamp(osg::Timer::instance()->tick()),
+ theLandCache(landCache),
+ theId(id)
+ {
+ estimateSize();
+ }
+ ossim_uint64 getId()const
+ {
+ return theId;
+ }
+ void access();
+
+ void setExtents(osg::ref_ptr<ossimPlanetExtents> extents);
+ void setTexture(ossim_uint32 idx, osg::ref_ptr<ossimPlanetImage> texture);
+ void setElevation(osg::ref_ptr<ossimPlanetImage> elevation);
+
+ void setLandCache(ossimPlanetLandCache* landCache);
+ const ossimPlanetExtents* getExtents()const
+ {
+ return theExtents.get();
+ }
+
+ void clearTextures();
+ ossimPlanetImage* getTexture(ossim_uint32 idx)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(idx < theTextureList.size())
+ {
+ return theTextureList[idx].get();
+ }
+
+ return 0;
+ }
+ ossimPlanetImage* getElevation()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return theElevation.get();
+ }
+ ossim_uint32 getTextureListSize()const
+ {
+ return theTextureList.size();
+ }
+ ossim_uint64 getNodeSizeInBytes()const;
+ osg::Timer_t timeStamp()const
+ {
+ return theTimeStamp;
+ }
+protected:
+ void protectedAccess();
+ void estimateSize();
+ /**
+ * Handles auto communicating the changed size to the cache that owns this node.
+ */
+ void adjustSize();
+ mutable osg::Timer_t theTimeStamp;
+ ossimPlanetReentrantMutex theMutex;
+ ossimPlanetLandCache* theLandCache;
+ ossim_uint64 theId;
+ ossim_uint32 theNodeSizeInBytes;
+ osg::ref_ptr<ossimPlanetExtents> theExtents;
+ std::vector<osg::ref_ptr<ossimPlanetImage> > theTextureList;
+ osg::ref_ptr<ossimPlanetImage> theElevation;
+};
+
+class ossimPlanetLandCache : public osg::Referenced
+{
+public:
+ friend class ossimPlanetLandCacheNode;
+ typedef std::map<ossim_uint64, osg::ref_ptr<ossimPlanetLandCacheNode> > ossimPlanetLandCacheType;
+ ossimPlanetLandCache(ossim_uint64 maxCacheSize=0, ossim_uint64 minCacheSize=0);
+
+ bool addNode(ossimPlanetLandCacheNode* node);
+ ossimPlanetLandCacheNode* getNode(ossim_uint64 id, bool allocateNewNodeIfNotPresent=true);
+ osg::ref_ptr<ossimPlanetLandCacheNode> removeNode(ossim_uint64 id);
+ void setCacheSize(ossim_uint64 maxCacheSize, ossim_uint64 minCacheSize);
+ ossim_uint64 getCacheSize()const;
+
+ void shrinkCache();
+ void clearCache();
+
+ void clearTexturesWithinExtents(osg::ref_ptr<ossimPlanetExtents> extents);
+ void clearAllWithinExtents(osg::ref_ptr<ossimPlanetExtents> extents);
+
+protected:
+ /**
+ * Will check to see if the cache exceeds max and if so shrinks until doesn't exceed min.
+ */
+ void protectedShrinkCache();
+
+ ossimPlanetReentrantMutex theMutex;
+ ossim_uint64 theMaxCacheSize;
+ ossim_uint64 theMinCacheSize; // used in shrinking the cache if exceeds the max
+ ossim_uint64 theCurrentCacheSize;
+ ossimPlanetLandCacheType theCacheMap;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandCullCallback.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandCullCallback.h
new file mode 100644
index 0000000..63de2ae
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandCullCallback.h
@@ -0,0 +1,55 @@
+#ifndef ossimPlanetLandCullCallback_HEADER
+#define ossimPlanetLandCullCallback_HEADER
+#include <osg/Node>
+#include <osg/Vec3d>
+#include <osg/NodeCallback>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+class ossimPlanetPagedLandLod;
+
+class OSSIMPLANET_DLL ossimPlanetLandCullCallback : public osg::NodeCallback
+{
+public:
+ ossimPlanetLandCullCallback();
+ ossimPlanetLandCullCallback(const ossimPlanetLandCullCallback& src)
+ :osg::NodeCallback(src),
+ theFreezeRequestFlag(src.theFreezeRequestFlag),
+ theCullingFlag(src.theCullingFlag),
+ theSplitMetric(src.theSplitMetric),
+ theSplitPriorityType(src.theSplitPriorityType),
+ theLineOfSiteValidFlag(src.theLineOfSiteValidFlag),
+ theLineOfSite(src.theLineOfSite)
+ {
+ }
+ ossimPlanetLandCullCallback* clone()const
+ {
+ return new ossimPlanetLandCullCallback(*this);
+ }
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
+ void setLineOfSite(const osg::Vec3d& lineOfSite);
+ void setLineOfSiteValidFlag(bool flag);
+ bool isLineOfSiteValid()const;
+
+ void setSplitMetricRatio(double ratio);
+ double getSplitMetricRatio()const;
+
+ void setSplitPriorityType(ossimPlanetPriorityType priorityType);
+ ossimPlanetPriorityType getSplitPriorityType()const;
+
+ void setCullingFlag(bool flag);
+ bool getCullingFlag()const;
+
+ void setFreezeRequestFlag(bool flag);
+ bool getFreezRequestFlag()const;
+protected:
+ void applyStandardCull(ossimPlanetPagedLandLod* n, osg::NodeVisitor* nv);
+ // void applyOrthoCull(ossimPlanetPagedLandLod* n, osg::NodeVisitor* nv);
+
+ bool theFreezeRequestFlag;
+ bool theCullingFlag;
+ double theSplitMetric;
+ ossimPlanetPriorityType theSplitPriorityType;
+ bool theLineOfSiteValidFlag;
+ osg::Vec3d theLineOfSite;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandNode.h
new file mode 100644
index 0000000..8c2530e
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandNode.h
@@ -0,0 +1,115 @@
+#ifndef ossimPlanetLandNode_HEADER
+#define ossimPlanetLandNode_HEADER
+#include <osg/PagedLOD>
+#include <osg/Texture2D>
+#include <osg/CoordinateSystemNode>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetLandGridNode.h>
+#include <ossimPlanet/ossimPlanetPagedRequestNode.h>
+#include <osg/Array>
+#include <osg/ref_ptr>
+#include <osg/Geometry>
+#include <osg/Texture2D>
+#include <ossim/base/ossimConstants.h>
+#include "ossimPlanetExport.h"
+#include "ossimPlanetLandSettings.h"
+#include "ossimPlanetBoundingBox.h"
+#include <ossimPlanet/ossimPlanetExport.h>
+
+namespace osgUtil
+{
+ class CullVisitor;
+}
+class OSSIMPLANET_DLL ossimPlanetLandNode : public osg::Group
+{
+public:
+ friend class ossimPlanetLand;
+ friend class ossimPlanetLandNodeDrawableCallback;
+ ossimPlanetLandNode(ossim_uint32 level = 0,
+ ossim_uint32 row = 0,
+ ossim_uint32 col = 0);
+ ossimPlanetLandNode(const ossimPlanetLandNode& plod,const osg::CopyOp& copyop);
+ virtual ~ossimPlanetLandNode();
+ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ossimPlanetLandNode *>(obj)!=NULL; }
+ virtual const char* className() const { return "PlanetLandNode"; }
+ virtual const char* libraryName() const { return ""; }
+
+ void setLandSettings(const osg::ref_ptr<ossimPlanetLandSettings>& settings);
+ void setTextureRequest(osg::ref_ptr<ossimPlanetPagedRequestNode> texture);
+ osg::ref_ptr<osg::Texture2D> getTexture();
+
+ ossim_uint32 getLevel()const;
+ ossim_uint32 getRow()const;
+ ossim_uint32 getCol()const;
+ bool getRemoveAllChildrenFlag()const
+ {
+ return theRemoveAllChildrenFlag;
+ }
+ void setRemoveAllChildrenFlag(bool flag)
+ {
+ theRemoveAllChildrenFlag = flag;
+ }
+ void createPatchGeometry();
+ void setPatchLocation(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ bool createPatchGeometryFlag=true);
+
+ virtual bool isLeaf()const;
+ virtual bool areAllChildrenLeaves()const;
+ virtual bool isCulled()const;
+ virtual bool areAllChildrenCulled()const;
+protected:
+ friend class ossimPlanetLandNodeUpdateCallback;
+ unsigned int theLevel;
+ unsigned int theRow;
+ unsigned int theCol;
+ osg::ref_ptr<ossimPlanetPagedRequestNode> theTextureRequest;
+
+ bool theTextureChangedFlag;
+ bool theElevationChangedFlag;
+ osg::ref_ptr<ossimPlanetLandSettings> theLandSettings;
+
+ mutable ossimPlanetReentrantMutex theMutex;
+ mutable osg::ref_ptr<osg::Geometry> theGeometry;
+
+ mutable bool theAddAllChildrenFlag;
+ mutable bool theRemoveAllChildrenFlag;
+ mutable bool theCulledFlag;
+ mutable bool thePreviousCulledFlag;
+ osg::Vec3d theCenterNormal;
+ osg::Vec3d theUlNormal;
+ osg::Vec3d theUrNormal;
+ osg::Vec3d theLrNormal;
+ osg::Vec3d theLlNormal;
+
+ osg::Vec3d theCenterPoint;
+ osg::Vec3d theUlPoint;
+ osg::Vec3d theUrPoint;
+ osg::Vec3d theLrPoint;
+ osg::Vec3d theLlPoint;
+ osg::ref_ptr<ossimPlanetBoundingBox> theBoundingBox;
+ osg::ref_ptr<ossimPlanetElevationGrid> theElevation;
+
+ virtual void createPoints(osg::Vec3Array *verts,
+ osg::Vec3Array *norms,
+ osg::Vec2Array *tcoords)=0;
+ virtual void handleUpdateTraversal(osg::NodeVisitor& nv);
+ virtual void handleCullTraversal(osg::NodeVisitor& nv);
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual void setupBoundaryNormals()=0;
+ virtual void applyElevation()=0;
+ virtual void adjustTexCoordinates();
+
+// void computeLocalToWorldTransformFromXYZ(double X, double Y, double Z, osg::Matrixd& localToWorld) const;
+// osg::Vec3d computeLocalPosition(const osg::Matrixd& worldToLocal, double X, double Y, double Z)const;
+
+ virtual bool addChild(Node *child);
+ virtual std::string createDbName()const;
+ virtual std::string createLevel0DbName()const;
+ const osg::ref_ptr<osg::Geometry> getParentGeometry()const;
+ osg::ref_ptr<osg::Geometry> getParentGeometry();
+ ossim_uint32 distanceToLeaf()const;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandNormalType.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandNormalType.h
new file mode 100644
index 0000000..5d06752
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandNormalType.h
@@ -0,0 +1,10 @@
+#ifndef ossimPlanetLandNormalType_HEADER
+#define ossimPlanetLandNormalType_HEADER
+
+enum ossimPlanetLandNormalType
+{
+ ossimPlanetLandNormalType_ELLIPSOIDAL = 0,
+ ossimPlanetLandNormalType_FLAT = 0
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandReaderWriter.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandReaderWriter.h
new file mode 100644
index 0000000..f73e10d
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandReaderWriter.h
@@ -0,0 +1,202 @@
+#ifndef ossimPlanetLandReaderWriter_HEADER
+#define ossimPlanetLandReaderWriter_HEADER
+#include <string>
+#include <ossim/base/ossimKeywordlist.h>
+#include <osgDB/ReaderWriter>
+#include <osg/MatrixTransform>
+#include <osg/Geometry>
+#include <osg/Texture2D>
+#include "ossimPlanetGridUtility.h"
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossimPlanet/ossimPlanetLandNormalType.h>
+/* #include <ossimPlanet/ossimPlanetElevationGrid.h> */
+#include <ossimPlanet/ossimPlanetBoundingBox.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetLandCache.h>
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <ossimPlanet/ossimPlanetShaderProgramSetup.h>
+#include <ossimPlanet/ossimPlanetElevationDatabaseGroup.h>
+#include <ossimPlanet/ossimPlanetLandCullCallback.h>
+class ossimPlanetLand;
+class ossimPlanetPagedLandLod;
+class ossimPlanetPagedLandLodCullCallback;
+class ossimPlanetTexture2D;
+class ossimPlanetLandReaderWriter : public osgDB::ReaderWriter
+{
+public:
+ typedef std::map<std::string, char> requestStringMapType;
+ ossimPlanetLandReaderWriter();
+
+ virtual const char* className()const;
+ virtual ReadResult readNode(const std::string& fileName, const Options*)const;
+
+ ossim_uint32 getId()const
+ {
+ return theId;
+ }
+
+ std::string createDbString(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+
+ void setModel(ossimPlanetGeoRefModel* geoModel);
+ const ossimPlanetGeoRefModel* model()const{return theModel.get();};
+ ossimPlanetGeoRefModel* model(){return theModel.get();};
+ void setLandNodeCullCallback(ossimPlanetLandCullCallback* callback);
+ bool getElevationEnabledFlag()const;
+ void setElevationEnabledFlag(bool elevationFlag);
+
+ ossim_float64 getHeightExag()const;
+ void setHeightExag(ossim_float64 exag);
+
+ ossim_uint32 getElevationPatchSize()const;
+ void setElevationPatchSize(ossim_uint32 densityLevel);
+
+ ossim_uint32 getMaxLevelDetail()const;
+ void setMaxLevelDetail(ossim_uint32 maxLevelDetail);
+
+ ossimFilename getElevationCacheDir()const;
+ void setElevationCacheDir(const ossimFilename& cacheDir);
+
+ const ossimPlanetGridUtility* gridUtility()const;
+ void setGridUtility(ossimPlanetGridUtility* utility);
+
+// void setMultiTextureLayers(osg::ref_ptr<ossimPlanetTextureLayerGroup> textureLayers);
+ void setReferenceLayer(osg::ref_ptr<ossimPlanetTextureLayerGroup> reference);
+ void setOverlayLayers(osg::ref_ptr<ossimPlanetTextureLayerGroup> overlays);
+ void setMipMappingFlag(bool flag);
+ bool getMipMappingFlag()const;
+
+ void setMultiTextureEnableFlag(bool flag);
+ bool getMultiTextureEnableFlag()const;
+
+ void setLandCache(osg::ref_ptr<ossimPlanetLandCache> landCache);
+
+ void setElevationDatabase(osg::ref_ptr<ossimPlanetElevationDatabaseGroup> databaseGroup);
+ osg::ref_ptr<ossimPlanetElevationDatabaseGroup> getElevationGroup();
+ const osg::ref_ptr<ossimPlanetElevationDatabaseGroup> getElevationGroup()const;
+
+protected:
+ enum ossimPlanetLandReaderWriterGeomType
+ {
+ ossimPlanetLandReaderWriterGeomType_NONE = 0,
+ ossimPlanetLandReaderWriterGeomType_TEXTURE = 1,
+ ossimPlanetLandReaderWriterGeomType_GEOM = 2,
+ ossimPlanetLandReaderWriterGeomType_LOD = 4
+ };
+ mutable ossimPlanetReentrantMutex theMutex;
+ ossim_uint32 theId;
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+ ossimPlanetLandType theLandType;
+ ossim_uint32 theMaxLevelDetail;
+ double theHeightExag;
+/* ossim_uint32 theElevationDensityLevel; */
+ ossim_uint32 theElevationPatchSize;
+ bool theElevationEnabledFlag;
+ ossimFilename theElevationCacheDir;
+ bool theMipMappingFlag;
+ osg::ref_ptr<ossimPlanetGridUtility> theGrid;
+ osg::ref_ptr<ossimPlanetGridUtility> theElevationGrid;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> theReferenceLayer;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> theOverlayLayers;
+/* osg::ref_ptr<ossimPlanetTextureLayer> theTextureLayer; */
+ osg::ref_ptr<ossimPlanetElevationDatabaseGroup> theElevationDatabase;
+ bool theMultiTextureEnableFlag;
+ osg::ref_ptr<ossimPlanetLandCache> theLandCache;
+ osg::ref_ptr<ossimPlanetLandCullCallback> theCullNodeCallback;
+ mutable osg::ref_ptr<osg::Texture2D> theBlankTexture;
+ /* virtual osgDB::ReaderWriter::ReadResult local_readNode(const std::string& filename, */
+/* const Options* options)const; */
+
+ virtual bool extractValues(const std::string& filename,
+ ossim_uint32 &level,
+ ossim_uint32 &row,
+ ossim_uint32 &col,
+ ossim_uint32 &id,
+ ossimPlanetLandReaderWriterGeomType &geomType)const;
+
+ void newTexture(std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ ossimPlanetImage::ossimPlanetImageStateType& textureState)const;
+
+ osg::ref_ptr<osg::MatrixTransform> newGeometry(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
+ osg::ref_ptr<ossimPlanetImage> elevationGrid,
+/* osg::ref_ptr<ossimPlanetElevationGrid> elevationGrid, */
+ ossimPlanetBoundingBox& box,
+ bool& useClusterCullingCallback,
+ osg::Vec3d& clusterControlPoint,
+ osg::Vec3d& clusterCenterNormal,
+ double& minDotProduct,
+ double& maxClusterCullingRadius)const;
+ virtual void createPoints(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ osg::ref_ptr<ossimPlanetImage> elevationGrid,
+/* osg::ref_ptr<ossimPlanetElevationGrid> elevationGrid, */
+ osg::Vec3Array *verts,
+ osg::Vec3Array *norms,
+ osg::Vec2Array *tcoords,
+ osg::Matrixd& localToWorld,
+ ossimPlanetBoundingBox& box,
+ bool& useClusterCullingCallback,
+ osg::Vec3d& clusterControlPoint,
+ osg::Vec3d& clusterCenterNormal,
+ double& minDotProduct,
+ double& maxClusterCullingRadius)const;
+
+
+ void initSupportAttributes(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ osg::Vec3d& centerPoint,
+ osg::Vec3d& ulPoint,
+ osg::Vec3d& urPoint,
+ osg::Vec3d& lrPoint,
+ osg::Vec3d& llPoint,
+ osg::Vec3d& centerNormal,
+ osg::Vec3d& ulNormal,
+ osg::Vec3d& urNormal,
+ osg::Vec3d& lrNormal,
+ osg::Vec3d& llNormal,
+ ossimPlanetBoundingBox& box,
+ std::vector<ossimPlanetBoundingBox>& childrenBounds,
+ const osg::MatrixTransform& transform)const;
+ void createBounds(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ ossimPlanetBoundingBox& bounds,
+ const osg::MatrixTransform& transform)const;
+ osg::Vec3d normal(double x, double y, double z)const;
+
+/* osg::ref_ptr<ossimPlanetElevationGrid> newElevation(ossim_uint32 level, */
+/* ossim_uint32 row, */
+/* ossim_uint32 col)const; */
+/* osg::ref_ptr<ossimPlanetElevationGrid> getCachedElevation(ossim_uint32 level, */
+/* ossim_uint32 row, */
+/* ossim_uint32 col)const; */
+ osg::ref_ptr<ossimPlanetImage> newElevation(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const;
+ osg::ref_ptr<ossimPlanetImage> getCachedElevation(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const;
+/* void writeElevationToCache(ossim_uint32 level, */
+/* ossim_uint32 row, */
+/* ossim_uint32 col, */
+/* osg::ref_ptr<ossimPlanetElevationGrid> elevation)const; */
+ void writeElevationToCache(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ osg::ref_ptr<ossimPlanetImage> elevation)const;
+
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandTextureRequest.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandTextureRequest.h
new file mode 100644
index 0000000..7671766
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandTextureRequest.h
@@ -0,0 +1,226 @@
+#ifndef ossimPlanetLandTextureRequest_HEADER
+#define ossimPlanetLandTextureRequest_HEADER
+#include <vector>
+#include <osg/Node>
+#include <osg/ref_ptr>
+#include <osg/Texture2D>
+#include <osg/NodeCallback>
+#include <osg/MatrixTransform>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetBoundingBox.h>
+#include <iostream>
+#include <ossimPlanet/ossimPlanetTexture2D.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+
+class ossimPlanetLandTextureRequest : public osg::Node
+{
+public:
+ ossimPlanetLandTextureRequest(ossim_uint32 level=0,
+ ossim_uint32 row=0,
+ ossim_uint32 col=0,
+ const std::vector<osg::ref_ptr<osg::Texture2D> >& textures=std::vector<osg::ref_ptr<osg::Texture2D> >())
+ :osg::Node(),
+ theLevel(level),
+ theRow(row),
+ theCol(col),
+ theTextures(textures)/* , */
+/* theClusterParametersSet(false) */
+ {
+ }
+ virtual ~ossimPlanetLandTextureRequest()
+ {
+ }
+ void setTextures(const std::vector<osg::ref_ptr<osg::Texture2D> >& textures)
+ {
+ theTextures = textures;
+ }
+ void setTransform(osg::ref_ptr<osg::Node> transform)
+ {
+ theTransform = transform;
+ }
+ void setCullCallback(osg::ref_ptr<osg::NodeCallback> callback)
+ {
+ theCullCallback = callback;
+ }
+ osg::ref_ptr<osg::Node> getTransform()
+ {
+ return theTransform;
+ }
+ std::vector<osg::ref_ptr<osg::Texture2D> >& getTextures()
+ {
+ return theTextures;
+ }
+ osg::ref_ptr<osg::NodeCallback> getCullCallback()
+ {
+ return theCullCallback;
+ }
+ ossim_uint32 getLevel()const
+ {
+ return theLevel;
+ }
+ ossim_uint32 getRow()const
+ {
+ return theRow;
+ }
+ ossim_uint32 getCol()const
+ {
+ return theCol;
+ }
+
+ void setCenterPoint(osg::Vec3d& centerPoint)
+ {
+ theCenterPoint = centerPoint;
+ }
+ void setUlPoint(osg::Vec3d& ulPoint)
+ {
+ theUlPoint = ulPoint;
+ }
+ void setUrPoint(osg::Vec3d& urPoint)
+ {
+ theUrPoint = urPoint;
+ }
+ void setLrPoint(osg::Vec3d& lrPoint)
+ {
+ theLrPoint = lrPoint;
+ }
+ void setLlPoint(osg::Vec3d& llPoint)
+ {
+ theLlPoint = llPoint;
+ }
+ void setCenterNormal(osg::Vec3d& centerNormal)
+ {
+ theCenterNormal = centerNormal;
+ }
+ void setUlNormal(osg::Vec3d& ulNormal)
+ {
+ theUlNormal = ulNormal;
+ }
+ void setUrNormal(osg::Vec3d& urNormal)
+ {
+ theUrNormal = urNormal;
+ }
+ void setLrNormal(osg::Vec3d& lrNormal)
+ {
+ theLrNormal = lrNormal;
+ }
+ void setLlNormal(osg::Vec3d& llNormal)
+ {
+ theLlNormal = llNormal;
+ }
+ osg::Vec3d centerPoint()const
+ {
+ return theCenterPoint;
+ }
+ osg::Vec3d ulPoint()const
+ {
+ return theUlPoint;
+ }
+ osg::Vec3d urPoint()const
+ {
+ return theUrPoint;
+ }
+ osg::Vec3d lrPoint()const
+ {
+ return theLrPoint;
+ }
+ osg::Vec3d llPoint()const
+ {
+ return theLlPoint;
+ }
+ osg::Vec3d centerNormal()const
+ {
+ return theCenterNormal;
+ }
+ osg::Vec3d ulNormal()const
+ {
+ return theUlPoint;
+ }
+ osg::Vec3d urNormal()const
+ {
+ return theUrNormal;
+ }
+ osg::Vec3d lrNormal()const
+ {
+ return theLrNormal;
+ }
+ osg::Vec3d llNormal()const
+ {
+ return theLlNormal;
+ }
+
+ void setBoundingBox(osg::ref_ptr<ossimPlanetBoundingBox> bounds)
+ {
+ theBoundingBox = bounds;
+ }
+ osg::ref_ptr<ossimPlanetBoundingBox> boundingBox()
+ {
+ return theBoundingBox;
+ }
+ const osg::ref_ptr<ossimPlanetBoundingBox> boundingBox()const
+ {
+ return theBoundingBox;
+ }
+ void setChildrenBounds(const std::vector<ossimPlanetBoundingBox>& childrenBounds)
+ {
+ theChildrenBounds = childrenBounds;
+ }
+ const std::vector<ossimPlanetBoundingBox>& childrenBounds()const
+ {
+ return theChildrenBounds;
+ }
+ ossimPlanetImage::ossimPlanetImageStateType getTextureState()const
+ {
+ return theTextureState;
+ }
+ void setTextureState(ossimPlanetImage::ossimPlanetImageStateType state)
+ {
+ theTextureState = state;
+ }
+
+/* void setClusterCullValues(bool useClusterCulling, */
+/* const osg::Vec3& controlPoint, */
+/* const osg::Vec3& normal, */
+/* double deviation, */
+/* double radius) */
+/* { */
+/* theClusterParametersSet = true; */
+/* theUseClusterCulling = useClusterCulling; */
+/* theClusterCullingControlPoint = controlPoint; */
+/* theClusterCullingNormal = normal; */
+/* theClusterCullingDeviation = deviation; */
+/* theClusterCullingRadius = radius; */
+/* } */
+
+protected:
+ ossim_uint32 theLevel;
+ ossim_uint32 theRow;
+ ossim_uint32 theCol;
+ std::vector<osg::ref_ptr<osg::Texture2D> > theTextures;
+ osg::ref_ptr<osg::Node> theTransform;
+ osg::ref_ptr<osg::NodeCallback> theCullCallback;
+
+ osg::Vec3d theCenterPoint;
+ osg::Vec3d theUlPoint;
+ osg::Vec3d theUrPoint;
+ osg::Vec3d theLrPoint;
+ osg::Vec3d theLlPoint;
+ osg::Vec3d theCenterNormal;
+ osg::Vec3d theUlNormal;
+ osg::Vec3d theUrNormal;
+ osg::Vec3d theLrNormal;
+ osg::Vec3d theLlNormal;
+ osg::ref_ptr<ossimPlanetBoundingBox> theBoundingBox;
+ std::vector<ossimPlanetBoundingBox> theChildrenBounds;
+ ossimPlanetImage::ossimPlanetImageStateType theTextureState;
+
+
+/* bool theClusterParametersSet; */
+/* bool theUseClusterCulling; */
+/* osg::Vec3d theClusterCullingControlPoint; */
+/* osg::Vec3d theClusterCullingNormal; */
+/* double theClusterCullingDeviation; */
+/* double theClusterCullingRadius; */
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLandTreeNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLandTreeNode.h
new file mode 100644
index 0000000..58cb53b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLandTreeNode.h
@@ -0,0 +1,26 @@
+#ifndef ossimPlanetLandTreeNode_HEADER
+#define ossimPlanetLandTreeNode_HEADER
+#include <osg/Node>
+
+class ossimPlanetLandTreeNode : public osg::Node
+{
+public:
+ ossimPlanetLandTreeNode(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col);
+
+protected:
+ ossim_uint32 theLevel;
+ ossim_uint32 theRow;
+ ossim_uint32 theCol;
+ ossimPlanetLandTreeNode* theParent;
+ ossimPlanetLandTreeNode* theRightNeighbor;
+ ossimPlanetLandTreeNode* theLeftNeighbor;
+ ossimPlanetLandTreeNode* theTopNeighbor;
+ ossimPlanetLandTreeNode* theBottomNeighbor;
+ ossimRefPtr<ossimPlanetLandTreeNode> theChildren[4];
+
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLatLonHud.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLatLonHud.h
new file mode 100644
index 0000000..1fc17d1
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLatLonHud.h
@@ -0,0 +1,86 @@
+#ifndef ossimPlanetLatLonHud_HEADER
+#define ossimPlanetLatLonHud_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <osgText/Text>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/LineWidth>
+#include <osg/Projection>
+#include <osg/CameraNode>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetCompass.h>
+class ossimPlanet;
+namespace osg
+{
+ class LineWidth;
+}
+class OSSIMPLANET_EXPORT ossimPlanetLatLonHud : public ossimPlanetLayer
+{
+public:
+ ossimPlanetLatLonHud();
+ virtual void traverse(osg::NodeVisitor& nv);
+ osg::Vec4 getCrossHairColor()const;
+ osg::Vec4 getTextColor()const;
+ void setCrosshairColor(const osg::Vec4& color);
+ void setTextColor(const osg::Vec4& color);
+ void setFont(const ossimString& fontFile);
+ void setLatDisplayString(const ossimString& latDisplayString);
+ void setLonDisplayString(const ossimString& lonDisplayString);
+ void setCharacterSize(float size);
+ void setViewport(osg::ref_ptr<osg::Viewport> viewport);
+ void setAutoUpdateFlag(bool flag);
+ void setCompassTexture(const ossimFilename& compass);
+// void setCompassTexture(const ossimFilename& ring,
+// const ossimFilename& interior);
+
+ virtual void execute(const ossimPlanetAction& action);
+
+protected:
+ void initialize();
+ void updatePosition();
+ osg::ref_ptr<osg::CameraNode> theCameraNode;
+/* osg::ref_ptr<osg::Projection> theProjection; */
+ osg::ref_ptr<osgText::Text> thePositionText;
+
+ osg::ref_ptr<osgText::Text> theLookText;
+ osg::ref_ptr<osgText::Text> theEyeText;
+ osg::ref_ptr<osgText::Text> theRangeText;
+
+ osg::ref_ptr<osg::Geode> theGeode;
+ osg::ref_ptr<osg::Viewport> theViewport;
+ osg::ref_ptr<osg::Geometry> theCrosshair;
+ osg::Vec3d theLineOfSiteLatLon;
+ osg::Vec3d theNadirLatLon;
+ double theRange;
+ double theAltitude;
+ osg::Vec4 theTextColor;
+ osg::Vec4 theShadowTextColor;
+ osg::Vec4 theCrosshairColor;
+ osg::ref_ptr<osg::LineWidth> theCrosshairLineWidth;
+ bool theAutoUpdateFlag;
+ mutable bool theFontChanged;
+ float theCharacterSize;
+ bool theCharacterSizeDirtyFlag;
+ ossimString theFontName;
+ osg::ref_ptr<osgText::Font> theFont;
+
+
+ ossimString theLookLabel;
+ ossimString theEyeLabel;
+ ossimString theRangeLabel;
+ ossimString theLookDisplayString;
+ ossimString theEyeDisplayString;
+
+ ossimString theLatDisplayString;
+ ossimString theLonDisplayString;
+
+
+ bool theInitializedFlag;
+ mutable OpenThreads::ReentrantMutex theMutex;
+ bool theViewportChangedFlag;
+ osg::ref_ptr<ossimPlanetCompass> theCompass;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLayer.h
new file mode 100644
index 0000000..bfa119a
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLayer.h
@@ -0,0 +1,58 @@
+#ifndef ossimPlanetLayer_HEADER
+#define ossimPlanetLayer_HEADER
+#include <osg/Group>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetNode.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+
+class ossimPlanet;
+
+class OSSIMPLANET_DLL ossimPlanetLayer :public ossimPlanetNode
+{
+public:
+ friend class ossimPlanetLayerUpdateCallback;
+
+ ossimPlanetLayer();
+ virtual ~ossimPlanetLayer();
+
+ virtual void execute(const ossimPlanetAction& action);
+
+ virtual void setModel(ossimPlanetGeoRefModel* model)
+ {
+ theModel = model;
+ }
+ const ossimPlanetGeoRefModel* model()const
+ {
+ return theModel.get();
+ }
+ ossimPlanetGeoRefModel* model()
+ {
+ return theModel.get();
+ }
+ virtual void setPlanet(ossimPlanet* planet)
+ {
+ thePlanet = planet;
+ }
+ ossimPlanet* planet()
+ {
+ return thePlanet;
+ }
+ const ossimPlanet* planet()const
+ {
+ return thePlanet;
+ }
+ virtual void needsRemoving(osg::Node* /*node*/){}
+ static ossimPlanetLayer* findLayer(osg::Node* startNode);
+ static ossimPlanetLayer* findLayer(osg::NodePath& currentNodePath);
+
+ virtual void traverse(osg::NodeVisitor& nv);
+
+protected:
+ ossimPlanet* thePlanet;
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLayerFactory.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLayerFactory.h
new file mode 100644
index 0000000..131f139
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLayerFactory.h
@@ -0,0 +1,21 @@
+#ifndef ossimPlanetLayerFactory_HEADER
+#define ossimPlanetLayerFactory_HEADER
+#include "ossimPlanetLayerFactoryBase.h"
+#include <osg/ref_ptr>
+
+class ossimPlanetLayerFactory : public ossimPlanetLayerFactoryBase
+{
+public:
+ ossimPlanetLayerFactory();
+ virtual ~ossimPlanetLayerFactory();
+
+ static ossimPlanetLayerFactory* instance();
+
+ virtual ossimPlanetLayer* create(const ossimString& type)const;
+protected:
+ static ossimPlanetLayerFactory* theInstance;
+
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLayerFactoryBase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLayerFactoryBase.h
new file mode 100644
index 0000000..5a0b521
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLayerFactoryBase.h
@@ -0,0 +1,15 @@
+#ifndef ossimPlanetLayerFactoryBase_HEADER
+#define ossimPlanetLayerFactoryBase_HEADER
+#include <osg/Referenced>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+class ossimPlanetLayer;
+class OSSIMPLANET_DLL ossimPlanetLayerFactoryBase : public osg::Referenced
+{
+public:
+ ossimPlanetLayerFactoryBase(){}
+
+ virtual ossimPlanetLayer* create(const ossimString& type)const=0;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLayerRegistry.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLayerRegistry.h
new file mode 100644
index 0000000..fa04363
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLayerRegistry.h
@@ -0,0 +1,39 @@
+#ifndef ossimPlanetLayerRegistry_HEADER
+#define ossimPlanetLayerRegistry_HEADER
+#include "ossimPlanetExport.h"
+#include <OpenThreads/ReadWriteMutex>
+#include <OpenThreads/ScopedLock>
+#include <vector>
+#include <ossim/base/ossimString.h>
+#include "ossimPlanetLayerFactoryBase.h"
+#include <osg/ref_ptr>
+
+class ossimPlanetLayer;
+class ossimPlanetLayerRegistry
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetLayerFactoryBase> > FactoryListType;
+
+ ossimPlanetLayerRegistry();
+ ~ossimPlanetLayerRegistry();
+ static ossimPlanetLayerRegistry* instance();
+ void finalize();
+
+ /**
+ * @param type is the type name of the layer to create
+ */
+ ossimPlanetLayer* create(const ossimString& type)const;
+
+ void registerFactory(ossimPlanetLayerFactoryBase* factory,
+ bool insertFrontFlag=false);
+ void unregisterFactory(const ossimPlanetLayerFactoryBase* factory);
+
+protected:
+ bool hasFactory(const ossimPlanetLayerFactoryBase* factory)const;
+
+ mutable OpenThreads::ReadWriteMutex theFactoryListMutex;
+ static ossimPlanetLayerRegistry* theInstance;
+ FactoryListType theFactoryList;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLookAt.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLookAt.h
new file mode 100644
index 0000000..765b4cd
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLookAt.h
@@ -0,0 +1,230 @@
+#ifndef ossimPlanetLookAt_HEADER
+#define ossimPlanetLookAt_HEADER
+#include <osg/Referenced>
+#include <ossim/base/ossimString.h>
+#include <sstream>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <iostream>
+#include <iomanip>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimXmlNode.h>
+
+class OSSIMPLANET_DLL ossimPlanetLookAt : public osg::Referenced
+{
+public:
+ ossimPlanetLookAt()
+ :osg::Referenced(),
+ theLat(0.0),
+ theLon(0.0),
+ theAltitude(0.0),
+ theHeading(0.0),
+ thePitch(0.0),
+ theRoll(0.0),
+ theRange(0.0),
+ theMode(ossimPlanetAltitudeMode_CLAMP_TO_GROUND)
+ {
+ }
+ ossimPlanetLookAt(const ossimPlanetLookAt& src)
+ :osg::Referenced(),
+ theLat(src.theLat),
+ theLon(src.theLon),
+ theAltitude(src.theAltitude),
+ theHeading(src.theHeading),
+ thePitch(src.thePitch),
+ theRoll(src.theRoll),
+ theRange(src.theRange),
+ theMode(src.theMode)
+ {
+ }
+ ossimPlanetLookAt(double lat, double lon, double altitude,
+ double heading, double pitch, double roll,
+ double range, ossimPlanetAltitudeMode mode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND)
+ {
+ setAll(lat, lon, altitude, heading, pitch, roll, range, mode);
+ }
+ virtual ossimPlanetLookAt* clone()const
+ {
+ return new ossimPlanetLookAt(*this);
+ }
+
+ void setAll(double lat, double lon, double altitude,
+ double heading, double pitch, double roll,
+ double range, ossimPlanetAltitudeMode mode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND)
+ {
+ theLat = lat;
+ theLon = lon;
+ theAltitude = altitude;
+ theHeading = heading;
+ thePitch = pitch;
+ theRoll = roll;
+ theRange = range;
+ theMode = mode;
+ }
+ void setLat(double value)
+ {
+ theLat = value;
+ }
+ double lat()const
+ {
+ return theLat;
+ }
+ void setLon(double value)
+ {
+ theLon = value;
+ }
+ double lon()const
+ {
+ return theLon;
+ }
+ void setAltitude(double value)
+ {
+ theAltitude = value;
+ }
+ double altitude()const
+ {
+ return theAltitude;
+ }
+ void setHeading(double value)
+ {
+ theHeading = value;
+ }
+ double heading()const
+ {
+ return theHeading;
+ }
+ void setPitch(double value)
+ {
+ thePitch = value;
+ }
+ double pitch()const
+ {
+ return thePitch;
+ }
+ void setRoll(double value)
+ {
+ theRoll = value;
+ }
+ double roll()const
+ {
+ return theRoll;
+ }
+ void setRange(double value)
+ {
+ theRange = value;
+ }
+ double range()const
+ {
+ return theRange;
+ }
+ void setAltitudeMode(ossimPlanetAltitudeMode mode)
+ {
+ theMode = mode;
+ }
+ ossimPlanetAltitudeMode altitudeMode()const
+ {
+ return theMode;
+ }
+ ossimString toNavigationString()const
+ {
+ std::ostringstream out;
+
+ out << std::setprecision(15)
+ << ":navigator gotolookat "
+ << theLat << " "
+ << theLon << " "
+ << theAltitude << " "
+ << theHeading << " "
+ << thePitch << " "
+ << theRoll << " "
+ << theRange << " "
+ << modeToString(theMode);
+
+ return ossimString(out.str().c_str());
+ }
+ ossimString toKml()const
+ {
+ std::ostringstream out;
+ out << std::setprecision(15) << "<LookAt>"
+ << "<latitude>" << theLat << "</latitude>"
+ << "<longitude>" << theLon << "</longitude>"
+ << "<altitude>" << theAltitude << "</altitude>"
+ << "<range>" << theRange << "</range>"
+ << "<tilt>" << thePitch << "</tilt>"
+ << "<heading>" << theHeading << "</heading>"
+ << "<altitudeMode>" << modeToString(theMode) << "</altitudeMode>"
+ << "</LookAt>";
+ return ossimString(out.str().c_str());
+ }
+ ossimRefPtr<ossimXmlNode> saveXml()const
+ {
+ ossimXmlNode* node = new ossimXmlNode();
+
+ node->setTag("ossimPlanetLookAt");
+ node->addChildNode("latitude", ossimString::toString(theLat));
+ node->addChildNode("longitude", ossimString::toString(theLon));
+ node->addChildNode("altitude", ossimString::toString(theAltitude));
+ node->addChildNode("range", ossimString::toString(theRange));
+ node->addChildNode("roll", ossimString::toString(theRoll));
+ node->addChildNode("tilt", ossimString::toString(thePitch));
+ node->addChildNode("heading", ossimString::toString(theHeading));
+ node->addChildNode("altitudeMode", modeToString(theMode));
+
+ return node;
+ }
+
+ bool loadXml(ossimRefPtr<ossimXmlNode> xmlNode);
+
+ static ossimString modeToString(ossimPlanetAltitudeMode mode)
+ {
+ ossimString altitudeMode = "clampToGround";
+
+ switch(mode)
+ {
+ case ossimPlanetAltitudeMode_RELATIVE_TO_GROUND:
+ {
+ altitudeMode = "relativeToGround";
+ break;
+ }
+ case ossimPlanetAltitudeMode_ABSOLUTE:
+ {
+ altitudeMode = "absolute";
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return altitudeMode;
+ }
+ static ossimPlanetAltitudeMode modeFromString(const ossimString& mode)
+ {
+ ossimPlanetAltitudeMode result = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ ossimString testString = mode;
+ testString = testString.downcase();
+ if(testString == "relativeToGround")
+ {
+ result = ossimPlanetAltitudeMode_RELATIVE_TO_GROUND;
+ }
+ else if(testString == "absolute")
+ {
+ result = ossimPlanetAltitudeMode_ABSOLUTE;
+ }
+
+ return result;
+ }
+
+
+protected:
+ double theLat;
+ double theLon;
+ double theAltitude;
+ double theHeading;
+ double thePitch;
+ double theRoll;
+ double theRange;
+ ossimPlanetAltitudeMode theMode;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetLsrSpaceTransform.h b/ossimPlanet/include/ossimPlanet/ossimPlanetLsrSpaceTransform.h
new file mode 100644
index 0000000..837f3a6
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetLsrSpaceTransform.h
@@ -0,0 +1,363 @@
+#ifndef ossimPlanetLsrSpaceTransform_HEADER
+#define ossimPlanetLsrSpaceTransform_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <osg/MatrixTransform>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ScopedLock>
+
+class ossimPlanetLsrSpaceTransform;
+class OSSIMPLANET_DLL ossimPlanetLsrSpaceTransformCallback : public ossimPlanetCallback
+ {
+ public:
+ virtual void lsrSpaceChanged(ossimPlanetLsrSpaceTransform* lsrSpace)=0;
+ };
+
+/**
+ * ossimPlanetLsrSpaceTransform allows one to talk to osg::Transform in the form of Euler angles and
+ * lat lon altitude where altitude is in meters. The Lsr stands for Local Space Reference. This manages
+ * a local space axis at te given <lat,lon,altitude> point.
+ */
+class OSSIMPLANET_DLL ossimPlanetLsrSpaceTransform : public osg::Transform,
+ public ossimPlanetCallbackListInterface<ossimPlanetLsrSpaceTransformCallback>
+{
+public:
+ /**
+ * Constructs a LsrSpace with a given geo ref model and orientation type.
+ * @param model The Geo Reference Model to use.
+ */
+ ossimPlanetLsrSpaceTransform(ossimPlanetGeoRefModel* model=0);
+
+ /**
+ * Copy contructor.
+ */
+ ossimPlanetLsrSpaceTransform(const ossimPlanetLsrSpaceTransform& lsrTransform,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ /**
+ * Allows one to change the geo reference model. Will apply the new model to the coordinates
+ * and dirty the bound.
+ *
+ * @param model The model to use to generates the lsrMatrix.
+ */
+ void setModel(ossimPlanetGeoRefModel* model);
+
+
+ /**
+ * Will copy the parameters only form one transform to the next.
+ *
+ * @param src This is the source to copy from.
+ */
+ void copyParametersOnly(const ossimPlanetLsrSpaceTransform& src)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ dirtyBound();
+ if(!theModel.valid())
+ {
+ theModel = src.theModel;
+ }
+ setHeadingPitchRoll(src.headingPitchRoll());
+ setLatLonAltitude(src.latLonAltitude());
+ setScale(src.scale());
+ theOrientationMode = src.theOrientationMode;
+ }
+ /**
+ * @return the pointer to the active model used by the transform.
+ */
+ const ossimPlanetGeoRefModel* model()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theModel.get();
+ }
+
+ /**
+ * @return the pointer to the active model used by the transform.
+ */
+ ossimPlanetGeoRefModel* model()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theModel.get();
+ }
+
+ /**
+ * This is the local to world transform matrix. It will extract out the translation, scale
+ * and orientation from the past in matrix and set the Lsr parameters.
+ *
+ * @param m The matrix to copy and extract the Lsr space parameters.
+ */
+ void setMatrix(const osg::Matrix& m);
+
+ /**
+ * @return the latitude position in degrees.
+ */
+ double lat()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theLatLonAltitude[0];
+ }
+
+ /**
+ * @return the longitutde position in degrees.
+ */
+ double lon()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theLatLonAltitude[1];
+ }
+
+ /**
+ * @return the altitdude in meters.
+ */
+ double altitude()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theLatLonAltitude[2];
+ }
+
+ /**
+ * @return latLonAltitude as a vector.
+ */
+ const osg::Vec3d& latLonAltitude()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theLatLonAltitude;
+ }
+
+ /**
+ * @return the model X coordinate of the model that was fromed from the inverse
+ * of the lat lon altitude.
+ */
+ double x()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theXYZ[0];
+ }
+
+ /**
+ * @return the model Y coordinate of the model that was fromed from the inverse
+ * of the lat lon altitude.
+ */
+ double y()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theXYZ[1];
+ }
+
+ /**
+ * @return the model Z coordinate of the model that was fromed from the inverse
+ * of the lat lon altitude.
+ */
+ double z()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theXYZ[2];
+ }
+
+ /**
+ * @return the model XYZ coordinate of the model that was fromed from the inverse
+ * of the lat lon altitude.
+ */
+ const osg::Vec3d& xyz()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theXYZ;
+ }
+
+ /**
+ * @return the heading orientation in degrees. indicates the rotation about the
+ * Nadir axis
+ */
+ double heading()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theHpr[0];
+ }
+
+ /**
+ * @return the pitch orientation in degrees. Indicates the rotation about the
+ * x-axis.
+ */
+ double pitch()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theHpr[1];
+ }
+
+ /**
+ * @return the roll orientation in degrees. Indicates the rotation about the
+ * y-axis.
+ */
+ double roll()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theHpr[2];
+ }
+
+ /**
+ * @return all values for heading pitch and roll.
+ */
+ const osg::Vec3d& headingPitchRoll()const{return theHpr;}
+
+ /**
+ * @return the x scale factor.
+ */
+ double scalex()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theScale[0];
+ }
+
+ /**
+ * @return the y scale factor
+ */
+ double scaley()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theScale[1];
+ }
+
+ /**
+ * @return the z-scale factor.
+ */
+ double scalez()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theScale[2];
+ }
+
+ /**
+ * @return the scale for x,y,z as a vector
+ */
+ const osg::Vec3d& scale()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theScale;
+ }
+
+ /**
+ * @param hpr contains the heading pitch and roll in that order for the orientation.
+ */
+ void setHeadingPitchRoll(const osg::Vec3d& hpr);
+
+ /**
+ * @param value contains the position lat lon and altitude where lat and lon
+ * are in degrees and altitude is in meters relative to the ellipsoid.
+ */
+ void setLatLonAltitude(const osg::Vec3d& value);
+
+
+ /**
+ * @param value contains the position lat lon altitude where lat lon are in degrees
+ * and altitude is in meters relative to the curren geoid contained in the
+ * ossimPlanetGeoRefModel.
+ */
+ void setLatLonAltitudeMeanSeaLevel(const osg::Vec3d& value);
+
+ /**
+ * @param value contains the values for the x-scale, y-scale, z-scale
+ * components.
+ */
+ void setScale(const osg::Vec3d& value);
+
+ /**
+ * @param xyz is the x,y,z values resulting from the conversion of lat,lon,altitude using the
+ * ossimPlanetGeoRefModel.
+ */
+ void setXYZ(const osg::Vec3d& xyz);
+
+ /**
+ * Override the base class Transform localToWorldMatrix.
+ */
+ virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
+
+ /**
+ * Override the base class world to local transforms
+ */
+ virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
+
+ /**
+ * Override the traverse to make sure that the model pointer is set and if the redraw flag is
+ * set then pass it up.
+ */
+ virtual void traverse(osg::NodeVisitor& nv);
+
+protected:
+ /**
+ * Will take the parameters such as lat,lon,altitude, heading, pitch, and roll, and scales
+ * and convert to it's localToWorld matrix form.
+ *
+ * @return true if successfull and flase otherwise.
+ */
+ bool parametersToMatrix();
+
+ /**
+ * Will take the matrix and extract out the parameters such as lat, lon, altitude, and
+ * heading pitch and roll and scales.
+ *
+ * param inputM the input matrix to decompose the parameters from. It will decompose to
+ * a local space reference axis.
+ */
+ void matrixToParameters(const osg::Matrix& inputM);
+
+ /**
+ * Will call the callbacks in the callback list and notify the listeners that
+ * the Lsr space transform changed.
+ */
+ void notifyLsrSpaceChanged();
+
+ /**
+ * thePropertyMutex is used to synchronize access to any property value.
+ */
+ mutable ossimPlanetReentrantMutex thePropertyMutex;
+
+ /**
+ * theOrientationMode specifies how to construct the matrix
+ * transform. This can be in OSSIM_LEFT_HANDED or OSSIM_RIGHT_HANDED.
+ */
+ ossimCoordSysOrientMode theOrientationMode;
+
+ /**
+ * Convenient pointer to hold direct access to the current GeoRefModel.
+ */
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+
+ /**
+ * The position in lat lon altitude where lat and lon are degrees and Altitude is
+ * meters.
+ */
+ osg::Vec3d theLatLonAltitude;
+
+ /**
+ * theXYZ holds the ossimlanetGeoRefModel result of going form lat, lon, altitude to the current
+ * x,y,z representation.
+ */
+ osg::Vec3d theXYZ;
+
+ /**
+ * theHpr holds the orientation parameters for heading, pitch and roll in degrees.
+ */
+ osg::Vec3d theHpr;
+
+ /**
+ * theScale holds the x,y,z, scale factors
+ */
+ osg::Vec3d theScale;
+
+ /**
+ * Convenient values for holding the theLocalToWorld transform.
+ */
+ mutable osg::Matrixd theLocalToWorld;
+
+ /**
+ * Convenient values for holding the inverse of theLocalToWorld transform.
+ */
+ mutable osg::Matrixd theInvLocalToWorld;
+
+ /**
+ * theRedrawFlag holds the value to specify if redraw is needed. Will be comunicated to
+ * the parent if needed.
+ */
+ bool theRedrawFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetManipulator.back b/ossimPlanet/include/ossimPlanet/ossimPlanetManipulator.back
new file mode 100644
index 0000000..ef31e24
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetManipulator.back
@@ -0,0 +1,125 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#ifndef OSSIM_PLANETMANIPULATOR
+#define OSSIM_PLANETMANIPULATOR 1
+
+#include <osgGA/MatrixManipulator>
+#include <osg/Quat>
+#include <ossim/base/ossimGpt.h>
+#include "ossimPlanetExport.h"
+
+class OSSIMPLANET_EXPORT ossimPlanetManipulator : public osgGA::MatrixManipulator
+{
+public:
+
+ ossimPlanetManipulator();
+
+ virtual const char* className() const { return "ossimPlanetManipulator"; }
+
+ /** set the minimum distance (as ratio) the eye point can be zoomed in towards the
+ center before the center is pushed forward.*/
+ void setMinimumDistance(float minimumDistance) { theMinimumAltitude=minimumDistance; }
+
+ /** get the minimum distance (as ratio) the eye point can be zoomed in */
+ float getMinimumDistance() const { return theMinimumAltitude; }
+
+
+ /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+ virtual void setByMatrix(const osg::Matrixd& matrix);
+
+ /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+ virtual void setByInverseMatrix(const osg::Matrixd& matrix) { setByMatrix(osg::Matrixd::inverse(matrix)); }
+
+ /** get the position of the manipulator as 4x4 Matrix.*/
+ virtual osg::Matrixd getMatrix() const;
+
+ /** get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/
+ virtual osg::Matrixd getInverseMatrix() const;
+
+ /** Get the FusionDistanceMode. Used by SceneView for setting up setereo convergence.*/
+ virtual osgUtil::SceneView::FusionDistanceMode getFusionDistanceMode() const { return osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE; }
+
+ /** Get the FusionDistanceValue. Used by SceneView for setting up setereo convergence.*/
+ virtual float getFusionDistanceValue() const { return _distance; }
+
+ /** Attach a node to the manipulator.
+ Automatically detaches previously attached node.
+ setNode(NULL) detaches previously nodes.
+ Is ignored by manipulators which do not require a reference model.*/
+ virtual void setNode(osg::Node*);
+
+ /** Return node if attached.*/
+ virtual const osg::Node* getNode() const;
+
+ /** Return node if attached.*/
+ virtual osg::Node* getNode();
+
+ /** Move the camera to the default position.
+ May be ignored by manipulators if home functionality is not appropriate.*/
+ virtual void home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
+
+ /** Start/restart the manipulator.*/
+ virtual void init(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
+
+ /** handle events, return true if handled, false otherwise.*/
+ virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
+
+ /** Get the keyboard and mouse usage of this manipulator.*/
+ virtual void getUsage(osg::ApplicationUsage& usage) const;
+
+protected:
+
+ virtual ~ossimPlanetManipulator();
+
+ /** Reset the internal GUIEvent stack.*/
+ void flushMouseEventStack();
+ /** Add the current mouse GUIEvent to internal stack.*/
+ void addMouseEvent(const osgGA::GUIEventAdapter& ea);
+
+ void computePosition(const osg::Vec3d& eye,const osg::Vec3d& lv,const osg::Vec3d& up);
+
+ /** For the give mouse movement calculate the movement of the camera.
+ Return true is camera has moved and a redraw is required.*/
+ bool calcMovement();
+
+ void trackball(osg::Vec3& axis,double& angle, double p1x, double p1y, double p2x, double p2y, double r);
+ double tb_project_to_sphere(double r, double x, double y);
+
+ /** Check the speed at which the mouse is moving.
+ If speed is below a threshold then return false, otherwise return true.*/
+ bool isMouseMoving();
+ bool computeIntersectionPoint(osg::Vec3d& intersection,
+ const osg::Vec3d& startPt = osg::Vec3d(0,0,0),
+ const osg::Vec3d& endPt=osg::Vec3d(0,0,0));
+ osg::Vec3d eyePosition()const;
+ // Internal event stack comprising last three mouse events.
+ osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1;
+ osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
+
+ osg::ref_ptr<osg::Node> _node;
+
+ double theMinimumAltitude;
+
+ bool _thrown;
+
+ osg::Vec3d _center;
+ osg::Quat _rotation;
+ double _distance;
+ double theCurrentAltitude;
+ double theMaxAltitude;
+};
+
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetManipulator.h b/ossimPlanet/include/ossimPlanet/ossimPlanetManipulator.h
new file mode 100644
index 0000000..6433c4c
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetManipulator.h
@@ -0,0 +1,309 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * OpenSceneGraph Public License for more details.
+ */
+
+#ifndef OSSIM_PLANETMANIPULATOR
+#define OSSIM_PLANETMANIPULATOR 1
+
+//#include <osgGA/MatrixManipulator>
+#include <osgGA/CameraManipulator>
+#include <osg/Quat>
+#include <ossim/base/ossimGpt.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetNavigator.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetViewMatrixBuilder.h>
+#include <osg/observer_ptr>
+#include <osg/Node>
+
+class ossimPlanet;
+
+//class OSSIMPLANET_DLL ossimPlanetManipulator : public osgGA::MatrixManipulator,
+class OSSIMPLANET_DLL ossimPlanetManipulator : public osgGA::CameraManipulator,
+public ossimPlanetActionReceiver
+{
+public:
+ ossimPlanetManipulator();
+
+ // osgGA::MatrixManipulator methods
+
+ virtual const char* className() const { return "ossimPlanetManipulator"; }
+
+ virtual void setByMatrix(const osg::Matrixd& matrix);
+ /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+
+ virtual void setByInverseMatrix(const osg::Matrixd& matrix) { setByMatrix(osg::Matrixd::inverse(matrix)); }
+ /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+
+ virtual osg::Matrixd getMatrix() const;
+ /** get the position of the manipulator as 4x4 Matrix.*/
+
+ virtual osg::Matrixd getInverseMatrix() const;
+ /** get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/
+
+ virtual void setNode(osg::Node*);
+ /** Get the FusionDistanceMode. Used by SceneView for setting up stereo convergence.*/
+ virtual osgUtil::SceneView::FusionDistanceMode getFusionDistanceMode() const { return osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE; }
+
+ /** Get the FusionDistanceValue. Used by SceneView for setting up stereo convergence.*/
+ virtual float getFusionDistanceValue() const { return theFusionDistance; }
+
+ /** Attach a node to the manipulator.
+ Automatically detaches previously attached node.
+ setNode(NULL) detaches previously nodes.
+ Is ignored by manipulators which do not require a reference model.*/
+
+ virtual const osg::Node* getNode() const;
+ /** Return node if attached.*/
+
+ virtual osg::Node* getNode();
+ /** Return node if attached.*/
+
+ virtual void home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
+ /** Move the camera to the default position.
+ May be ignored by manipulators if home functionality is not appropriate.*/
+
+ virtual void init(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
+ /** Start/restart the manipulator.*/
+
+ virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
+ /** handle events, return true if handled, false otherwise.*/
+
+ virtual void getUsage(osg::ApplicationUsage& usage) const;
+ /** Get the keyboard and mouse usage of this manipulator.*/
+
+
+ virtual void setLockToNode(osg::Node* node);
+ // new methods
+
+ virtual void getLatLonHgtHPR(double& lat, double& lon, double& hgt, double& heading, double& pitch, double& roll)const;
+
+ virtual void solveLookAt(double losLat, double losLon, double losHeight, double& heading, double& pitch, double& roll, double& range)const;
+
+ void playRecording();
+ void startRecording();
+ void stopRecording();
+ void saveRecording(std::ostream& out);
+ bool loadRecording(std::istream& in);
+
+ void extractLookFromParameters(ossimXmlNode* node,
+ double& lat,
+ double& lon,
+ double& alt,
+ double& h,
+ double& p,
+ double& r);
+
+
+
+ void setEventHandlingFlag(bool flag);
+ void setUseFrameEventForUpdateFlag(bool flag);
+ void setAutoCalculateIntersectionFlag(bool flag);
+ void setLosXYZ(const osg::Vec3d& losXYZ);
+
+ void updateNavigator();
+ // call theNavigator->update()
+ // Cocoa version temporarily needs this for now
+ ossimPlanetNavigator* navigator()
+ {
+ return theNavigator.get();
+ }
+
+ /**
+ * Will set the latitude for the view matrix.
+ *
+ * @param value is the latitude position of the view in degrees.
+ */
+ void setLatitude(double value);
+
+ /**
+ * Will set the longitude for the view matrix.
+ *
+ * @param value is the longitude position of the view in degrees.
+ */
+ void setLongitude(double value);
+
+ /**
+ * Will set the altitude for the view matrix.
+ *
+ * @param value is the altitude position of the view in meters.
+ * Currently this is absolute position on the ellipsoid.
+ */
+ void setAltitude(double value);
+
+
+ /**
+ * Will allow you to set the latitude, longitude and altitude in a single operation
+ *
+ * @param lat is the latitude position of the view in degrees.
+ * @param lon is the longitude position of the view in degrees.
+ * @param alt is the altitude position of the view in meters.
+ * Currently this is absolute position on the ellipsoid.
+ */
+ void setLatitudeLongitudeAltitude(double lat, double lon, double alt);
+
+ /**
+ * This is a convenience method that allows one to put the positional information
+ * in a single osg::Vec3d data type.
+ *
+ * @param pos is the is the latitude, longitude, altitude where the latitude is in
+ * pos[0] and longitude is in pos[1] and altitude is in pos[2]. the lat and lon
+ * values are in degrees where the altitude is in meters.
+ */
+ void setPosition(const osg::Vec3d& pos);
+
+ /**
+ * sets the heading orientation for the view. Note this indicates a rotation about the
+ * Z-axis.
+ *
+ * @param value indicates the heading in degrees to rotate around the Z axis.
+ */
+ void setHeading(double value);
+
+ /**
+ * Sets the pitch orientation for the view. Note this indicates a rotation about the
+ * X-axis.
+ *
+ * @param value indicates the pitch in degrees to rotate around the X-axis.
+ */
+ void setPitch(double value);
+
+ /**
+ * Set the roll orietation for the view. Note this indicates a rotation about the
+ * Y-axis.
+ */
+ void setRoll(double value);
+
+ /**
+ * sets the heading pitch and rool as a single operation.
+ *
+ * @param h indicates the heading in degrees to rotate around the Z axis.
+ * @param p indicates the pitch in degrees to rotate around the X axis.
+ * @param r indicates the roll in degrees to rotate around the y axis.
+ */
+ void setHeadingPitchRoll(double h, double p, double r);
+
+ /**
+ * This is a convenience method that allows one to put the positional information
+ * in a single osg::Vec3d data type.
+ *
+ * @param orien is the heading, pitch, and roll orientation of the view in degrees.
+ * the heading is in orien[0] and pitch is in orien[1] and the roll is in
+ * orien[2].
+ */
+ void setOrientation(const osg::Vec3d& orien);
+
+ /**
+ * Allows one to set the position and orientation as a single operation.
+ *
+ * @param lat is the latitude position of the view in degrees.
+ * @param lon is the longitude position of the view in degrees.
+ * @param alt is the altitude position of the view in meters.
+ * Currently this is absolute position on the ellipsoid.
+ * @param h indicates the heading in degrees to rotate around the Z axis.
+ * @param p indicates the pitch in degrees to rotate around the X axis.
+ * @param r indicates the roll in degrees to rotate around the y axis.
+ *
+ */
+ void setPositionAndOrientation(double lat, double lon, double altitude,
+ double h, double p, double r);
+
+ /**
+ * This is an added convenience method to take 2 3-d vectors as position
+ * and orientation
+ *
+ * @param pos is the is the latitude, longitude, altitude where the latitude is in
+ * pos[0] and longitude is in pos[1] and altitude is in pos[2]. the lat and lon
+ * values are in degrees where the altitude is in meters.
+ * @param orien is the heading, pitch, and roll orientation of the view in degrees.
+ * the heading is in orien[0] and pitch is in orien[1] and the roll is in
+ * orien[2].
+ *
+ */
+ void setPositionAndOrientation(const osg::Vec3d& pos,
+ const osg::Vec3d& orien);
+
+ ossimPlanetViewMatrixBuilder* viewMatrixBuilder(){return theViewMatrixBuilder.get();}
+ const ossimPlanetViewMatrixBuilder* viewMatrixBuilder()const{return theViewMatrixBuilder.get();}
+ virtual void execute(const ossimPlanetAction& a);
+
+ void initializeDefaultBindings(const ossimString& pathName=":navigator");
+
+protected:
+
+ class FromNodeCallback : public ossimPlanetLsrSpaceTransformCallback
+ {
+ public:
+ FromNodeCallback(ossimPlanetViewMatrixBuilder* vb)
+ :theViewMatrixBuilder(vb)
+ {
+ }
+ virtual void lsrSpaceChanged(ossimPlanetLsrSpaceTransform* /*lsrSpace*/)
+ {
+ if(theViewMatrixBuilder)
+ {
+ theViewMatrixBuilder->setLookFromNodeOffset(theViewMatrixBuilder->fromNode(),
+ theViewMatrixBuilder->fromRelativeHpr(),
+ theViewMatrixBuilder->fromRange(),
+ theViewMatrixBuilder->fromRelativeOrientationFlags());
+ }
+ }
+ ossimPlanetViewMatrixBuilder* theViewMatrixBuilder;
+ };
+
+ class ToNodeCallback : public ossimPlanetLsrSpaceTransformCallback
+ {
+ public:
+ ToNodeCallback(ossimPlanetViewMatrixBuilder* vb)
+ :theViewMatrixBuilder(vb)
+ {
+
+ }
+ virtual void lsrSpaceChanged(ossimPlanetLsrSpaceTransform* lsrSpace)
+ {
+ if(theViewMatrixBuilder)
+ {
+ theViewMatrixBuilder->setLookToNode(lsrSpace);
+ }
+ }
+ ossimPlanetViewMatrixBuilder* theViewMatrixBuilder;
+ };
+
+ virtual ~ossimPlanetManipulator();
+ virtual void updateViewMatrixNodes();
+
+ bool calculateLineOfSiteLatLonHeight(osg::Vec3d& latLonHeight);
+
+ osg::Vec3d eyePosition()const;
+
+ osg::ref_ptr<ossimPlanetNavigator> theNavigator;
+ mutable ossimPlanetReentrantMutex theMutex;
+ osg::ref_ptr<osg::Node> theNode;
+ bool theEventHandlingFlag;
+ bool theUseFrameEventForUpdateFlag;
+ bool theAutoCalculateIntersectionFlag;
+ ossimPlanet* thePlanet;
+ ossim_float32 theFusionDistance;
+
+ osg::ref_ptr<ossimPlanetViewMatrixBuilder> theViewMatrixBuilder;
+
+ osg::ref_ptr<osg::Node> theLockToNode;
+ osg::ref_ptr<osg::Node> theLockFromNode;
+
+ osg::ref_ptr<FromNodeCallback> theFromNodeCallback;
+ osg::ref_ptr<ToNodeCallback> theToNodeCallback;
+};
+
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetMessage.h b/ossimPlanet/include/ossimPlanet/ossimPlanetMessage.h
new file mode 100644
index 0000000..ede81c5
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetMessage.h
@@ -0,0 +1,48 @@
+#ifndef ossimPlanetMessage_HEADER
+#define ossimPlanetMessage_HEADER
+#include <ossim/base/ossimString.h>
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <vector>
+
+class OSSIMPLANET_DLL ossimPlanetMessage : public osg::Referenced
+{
+public:
+ typedef unsigned char DataType;
+ typedef std::vector<ossimPlanetMessage::DataType> StorageType;
+
+ ossimPlanetMessage(const ossimString& id=ossimString("") )
+ {
+ setId(id);
+ }
+ ossimPlanetMessage(const ossimString& id, const ossimString& data )
+ {
+ setId(id);
+ setData(data);
+ }
+ ossimPlanetMessage(const ossimString& id, const std::vector<char>& byteBuffer):
+ theId(id),
+ theData(byteBuffer.begin(), byteBuffer.end())
+ {
+ }
+ ossimPlanetMessage(const ossimString& id, const StorageType& buf):
+ theId(id),
+ theData(buf)
+ {
+ }
+ ossimPlanetMessage(const ossimPlanetMessage& src)
+ :theId(src.theId),
+ theData(src.theData){}
+ ossimPlanetMessage* clone()const{return new ossimPlanetMessage(*this);}
+ const ossimString& id()const{return theId;}
+ void setId(const ossimString& id){theId = id;}
+ void setData(const ossimPlanetMessage::StorageType& data){theData = data;}
+ void setData(const ossimString& data){theData.clear();theData.insert(theData.begin(), data.begin(), data.end());}
+ ossim_uint32 dataSize()const{return (ossim_uint32)theData.size();}
+ const ossimPlanetMessage::StorageType& data()const{return theData;}
+protected:
+ ossimString theId;
+ ossimPlanetMessage::StorageType theData;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetNavigator.h b/ossimPlanet/include/ossimPlanet/ossimPlanetNavigator.h
new file mode 100644
index 0000000..0563a2d
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetNavigator.h
@@ -0,0 +1,277 @@
+#ifndef ossimPlanetNavigator_HEADER
+#define ossimPlanetNavigator_HEADER
+
+#include <assert.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetPrimaryBody.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <osg/Timer>
+#include <osg/AnimationPath>
+#include <osg/ref_ptr>
+#include <osg/Referenced>
+#include <osg/Matrixd>
+//#include <osgGA/MatrixManipulator>
+#include <osgGA/CameraManipulator>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+
+class ossimPlanet;
+class OSSIMPLANET_DLL ossimPlanetNavigator : public osg::Referenced//,
+ //public ossimPlanetActionReceiver
+{
+public:
+ ossimPlanetNavigator(osg::ref_ptr<ossimPlanetPrimaryBody> p);
+ // assert(p);
+ ~ossimPlanetNavigator();
+
+ double lat() const
+ // latitude of eye in degrees
+ { return lat_; };
+
+ double lon() const
+ // longitude of eye in degrees
+ { return lon_; };
+
+ double elev() const
+ // elevation of eye in meters
+ { return zoom2Elevation(eyexyz_.z()); }
+
+ const osg::Vec3d& orientation() const
+ // eyepoint orientation in euler angles: heading (yaw), pitch, roll
+ { return eyehpr_; };
+
+ double metersToCenter() const;
+ // distance from eye to center of primary
+
+ void setLatLonHeight(double lat, double lon, double height);
+ void setHpr(double h, double p, double r);
+ // set the lat, lon, elevation above planet
+
+ virtual osg::Vec3d centerOfInterest() const;
+ // lat/lon/elev of center of interest in degrees/degrees/meters for CacheEngine purposes
+
+ virtual void update();
+ // update look/lat/lon/elev/navigation-quasimodes based on current navigation-quasimodes
+
+ void updateZoomParameters();
+ // update info needed to clamp/manage the eyepoint zoomin
+
+ const osg::ref_ptr<ossimPlanetPrimaryBody> primary() const
+ // the primary we are orbiting
+ { return primary_; }
+
+ // ActionReceiver features
+
+ virtual void execute(const ossimPlanetAction &a);
+ // execute action
+
+
+ // uncommented mystery routines under here
+
+ osg::Matrixd orientationLsrMatrix() const
+ { return orientationLsrMatrix(lat_, lon_, elev(), eyehpr_[0], eyehpr_[1], eyehpr_[2]); }
+
+ osg::Matrixd orientationLsrMatrix(double lat, double lon, double hgt, double h, double p, double r) const;
+
+ osg::Matrixd viewMatrix() const
+ { return viewMatrix(lat_, lon_, elev(), eyehpr_[0], eyehpr_[1], eyehpr_[2]); }
+
+ osg::Matrixd viewMatrix(double lat, double lon, double hgt, double h, double p, double r) const;
+
+ void setViewParameters(const osg::Matrixd& m);
+
+ void setPlanet(ossimPlanet* planet)
+ { thePlanet = planet; }
+
+ bool canSetLineOfSite() const
+ { return ((!zoominglos_ && !losLookingFlag_)||
+ (!losXYZValidFlag_||rotating_||looking_||flying_)); }
+
+ double pitchOffset() const
+ { return pitchOffset_; }
+
+ void setLosXYZ(const osg::Vec3d& losXYZ)
+ {
+ losXYZ_ = losXYZ;
+ losXYZValidFlag_ = !ossim::isnan(losXYZ[0]) && !ossim::isnan(losXYZ[1]) && !ossim::isnan(losXYZ[2]);
+ }
+
+ void setLosXYZValidFlag(bool flag)
+ { losXYZValidFlag_ = flag; }
+
+ bool gotZoomingLosFlag() const
+ { return zoominglos_; }
+
+ bool getLosLookingFlag() const
+ { return losLookingFlag_; }
+
+ void setLosLookingFlag(bool flag)
+ { losLookingFlag_ = flag; }
+
+ enum NavigatorAnimationMode { NAV_ANIMATION_NONE = 0, NAV_ANIMATION_RECORDING = 1, NAV_ANIMATION_PLAYBACK = 2 };
+
+ void solveLookAt(double losLat, double losLon, double losHeight,
+ double& heading, double& pitch, double& roll, double& range)const;
+ void solveEyeGivenLocalSpaceAndRange(osg::Vec3d& llh, // out lat lon height
+ osg::Vec3d& hpr, // output orientation
+ const osg::Vec3d& localPt,
+ const osg::Vec3d& localHpr,
+ double rangeInMeters)const;
+ void playRecording();
+ void startRecording();
+ void stopRecording();
+ void saveRecording(std::ostream& out);
+ bool loadRecording(std::istream& in);
+
+ void setUseTimedUpdateFlag(bool flag);
+
+ bool needsContinuousUpdate()const
+ {
+ return ((theAnimationMode==NAV_ANIMATION_PLAYBACK)||
+ rotating_||
+ zooming_||
+ zoominglos_||
+ looking_||
+ gotoing_||
+ gotoingelev_||
+ gotoset_||
+ flying_||
+ losLookingFlag_);
+ }
+ void setRedrawFlag(bool flag)
+ {
+ theRedrawFlag = flag;
+ }
+ bool redrawFlag()const
+ {
+ return theRedrawFlag;
+ }
+ osg::ref_ptr<ossimPlanetGeoRefModel> landModel();
+ const osg::ref_ptr<ossimPlanetGeoRefModel> landModel()const;
+ void gotoLatLonElevHpr(const string& placeName,
+ double latitude,
+ double longitude,
+ double elevation,
+ double h,
+ double p,
+ double r,
+ bool animateFlag=true);
+ void gotoLookAt(const ossimPlanetLookAt& lookInfo,bool animateFlag=true);
+protected:
+ void xmlExecute(const ossimPlanetXmlAction& action);
+ void destinationCommandExecute(const ossimPlanetDestinationCommandAction& action);
+
+ void updateLatLon(float x, float y);
+
+
+ // update lon_ and lat_ based on user input x,y in [-1,1] and elev()
+ void extractCameraParameters(ossimRefPtr<ossimXmlNode> node,
+ double& lat,
+ double& lon,
+ double& alt,
+ double& h,
+ double& p,
+ double& r)const;
+ void extractLookAtParameters(ossimRefPtr<ossimXmlNode> node,
+ ossimPlanetLookAt& look)const;
+ inline double zoom2Elevation(double zoomParameter) const
+ { return (-zoomParameter - 1.0)*primary_->radius(lat()); }
+
+ double pitchOffset_;
+
+ double lat_;
+ double lon_;
+ // current latitude and longitude of eye in degrees
+
+ osg::Vec3d eyexyz_;
+ // eyepoint position (z for zooming, xy unused)
+
+ osg::Vec3d eyehpr_;
+ // eyepoint orientation (heading/pitch/roll)
+
+ double zoomMin_;
+ double zoomMax_;
+ // min and max distances to zoom in and out
+
+ double fov_;
+ // GraphicsSystem::instance()->camera()->fov()
+
+ ossimPlanet* thePlanet;
+
+ osg::ref_ptr<ossimPlanetPrimaryBody> primary_;
+ // the primary we are observing (ie, the celestial body we orbit, ie probably the earth)
+
+ bool rotating_;
+ bool zooming_;
+ bool zoominglos_;
+ bool looking_;
+ bool endLooking_;
+ bool gotoing_;
+ bool gotoingelev_;
+ bool gotoset_;
+ bool flying_;
+ bool losLookingFlag_;
+ // current user navigation quasimodes
+
+ double targetLat_;
+ double targetLon_;
+ double targetLookZ_;
+ double targetStartLookZ_;
+ double targetStartLat_;
+ double targetStartLon_;
+ double targetStartLookH_;
+ double targetStartLookP_;
+ double targetStartLookR_;
+ double targetMidpointLookZ_;
+ double targetLookH_;
+ double targetLookP_;
+ double targetLookR_;
+
+ osg::Vec3d losXYZ_;
+ bool losXYZValidFlag_;
+
+ double updateRatePerSecond_;
+ osg::Timer_t lastUpdateTime_;
+
+ osg::Timer_t gotoStartTime_;
+ // data for going to a target location
+
+ double gotoLookDuration_;
+ // duration in seconds of movement in a gotolatlon and a look view snapback
+
+ osg::Timer_t endLookingStartTime_;
+ // time when user stopped looking around
+
+ double zoomScaleBaseline_;
+ // pfUnits elevation height of maximum user input sensitivity
+
+ double zoomScaleInput(float input) const;
+ // scale user input based on current zoom level and zoomScaleBaseline_
+
+ double baseInputLon_, baseInputLat_, baseInputZoom_, baseInputYaw_, baseInputPitch_;
+ // initial values for device input, so we can use relative device movement
+
+ double xFly_, yFly_;
+ // values specified by last flying action (which may be still active; flying_ will tell you)
+
+ struct LastAnimationParameter
+ {
+ osg::Quat quat;
+ osg::Vec3d orientation;
+ osg::Vec3d eye;
+ };
+ NavigatorAnimationMode theAnimationMode;
+ osg::ref_ptr<osg::AnimationPath> theAnimationPath;
+ LastAnimationParameter theLastAnimationParameter;
+ osg::Timer_t theAnimationStartTime;
+
+ mutable ossimPlanetReentrantMutex theMutex;
+ bool theUseTimedUpdateFlag;
+ bool theRedrawFlag;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetNetworkConnection.h b/ossimPlanet/include/ossimPlanet/ossimPlanetNetworkConnection.h
new file mode 100644
index 0000000..375ac3f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetNetworkConnection.h
@@ -0,0 +1,41 @@
+#ifndef ossimPlanetNetworkConnection_HEADER
+#define ossimPlanetNetworkConnection_HEADER
+
+// abstract interface to network.
+
+#include <string>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+
+class OSSIMPLANET_DLL ossimPlanetNetworkConnection
+{
+public:
+ ossimPlanetNetworkConnection(const std::string& name) : name_(name) {}
+ virtual ~ossimPlanetNetworkConnection() {}
+
+ const std::string& name() const
+ // name of the connection
+ { return name_; }
+
+ const std::string& error() const
+ // current error status, empty if no error.
+ { return error_; }
+
+ virtual void send(const ossimPlanetAction& a, const std::string& destination) = 0;
+ // send action to the specified destination host.
+
+ virtual void receive() = 0;
+ // read any pending incoming actions and execute them.
+ // should discard any incoming sent by me where destination is me or all
+
+protected:
+ std::string name_;
+ // name of the connection
+
+ std::string error_;
+ // current error status, empty if no error.
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetNode.h
new file mode 100644
index 0000000..cc7c397
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetNode.h
@@ -0,0 +1,255 @@
+#ifndef ossimPlanetNode_HEADER
+#define ossimPlanetNode_HEADER
+#include <osg/Group>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ReadWriteMutex>
+
+class ossimPlanetNode;
+class OSSIMPLANET_DLL ossimPlanetNodeCallback : public ossimPlanetCallback
+{
+public:
+ virtual void propertyChanged(ossimPlanetNode* /*node*/,
+ const ossimString& /*name*/){}
+ virtual void destructingNode(ossimPlanetNode* /*node*/){}
+ virtual void needsRedraw(ossimPlanetNode* /*node*/){}
+ virtual void nodeAdded(osg::Node* /*node*/){}
+ virtual void nodeRemoved(osg::Node* /*node*/){}
+
+protected:
+};
+
+
+class ossimPlanetLayer;
+class OSSIMPLANET_DLL ossimPlanetNode : public osg::Group,
+ public ossimPlanetCallbackListInterface<ossimPlanetNodeCallback>,
+ public ossimPlanetActionReceiver
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetNode> > NodeListType;
+
+ ossimPlanetNode();
+ virtual ~ossimPlanetNode();
+ static void remove(osg::Node* node);
+ virtual void setLayer(ossimPlanetLayer* layer)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theLayer = layer;
+ }
+ ossimPlanetLayer* layer()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theLayer;
+ }
+ const ossimPlanetLayer* layer()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theLayer;
+ }
+ virtual bool addChild( Node *child );
+ virtual bool insertChild( unsigned int index, Node *child );
+ virtual bool replaceChild( Node *origChild, Node* newChild );
+ bool removeChildren(unsigned int pos,unsigned int numChildrenToRemove);
+ bool enableFlag()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theEnableFlag;
+ }
+ virtual void setEnableFlag(bool flag)
+ {
+ bool changed = flag!=enableFlag();
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theEnableFlag = flag;
+ }
+ if(changed) setRedrawFlag(true);
+ notifyPropertyChanged(this, "enableFlag");
+ }
+ bool intersectFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+
+ return theIntersectableFlag;
+ }
+ virtual void setIntersectFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theIntersectableFlag = flag;
+ }
+ virtual void setRedrawFlag(bool flag);
+ bool redrawFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodeRedrawPropertyMutex);
+ return theRedrawFlag;
+ }
+ const ossimString& id()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theId;
+ }
+ virtual void setId(const ossimString& id)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theId = id;
+ }
+ notifyPropertyChanged(this, "id");
+ }
+ virtual void setName(const ossimString& value)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theName = value;
+ }
+ notifyPropertyChanged(this, "name");
+ }
+ const ossimString& name()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theName;
+ }
+ void name(ossimString& value)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ value = theName;
+ }
+ virtual void setDescription(const ossimString& value)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theDescription = value;
+ }
+ notifyPropertyChanged(this, "description");
+ }
+ const ossimString& description()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theDescription;
+ }
+ void description(ossimString& value)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ value = theDescription;
+ }
+ virtual osg::ref_ptr<ossimPlanetLookAt> lookAt()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theLookAt;
+ }
+ virtual const osg::ref_ptr<ossimPlanetLookAt> lookAt()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ return theLookAt;
+ }
+ virtual void lookAt(ossimPlanetLookAt& result)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ if(theLookAt.valid())
+ {
+ result = *theLookAt;
+ }
+ }
+ virtual void setLookAt(osg::ref_ptr<ossimPlanetLookAt> value)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodePropertyMutex);
+ theLookAt = value;
+ }
+ notifyPropertyChanged(this, "LookAt");
+ }
+ virtual void traverse(osg::NodeVisitor& nv);
+ virtual void execute(const ossimPlanetAction& action);
+
+ static ossimPlanetNode* findNode(osg::NodePath& currentNodePath);
+
+
+ virtual void notifyPropertyChanged(ossimPlanetNode* node, const ossimString& name);
+ virtual void notifyDestructing(ossimPlanetNode* node);
+ virtual void notifyNeedsRedraw();
+ virtual void notifyAddChild(osg::ref_ptr<osg::Node> node);
+ virtual void notifyRemoveChild(osg::ref_ptr<osg::Node> node);
+
+protected:
+ virtual void nodeAdded(osg::Node* /*node*/){}
+ virtual void nodeRemoved(osg::Node* /*node*/){}
+ mutable OpenThreads::ReentrantMutex thePlanetNodeRedrawPropertyMutex;
+ mutable OpenThreads::ReentrantMutex thePlanetNodePropertyMutex;
+
+ bool theEnableFlag;
+ bool theIntersectableFlag;
+ ossimString theId;
+ ossimString theName;
+ ossimString theDescription;
+ bool theRedrawFlag;
+ osg::ref_ptr<ossimPlanetLookAt> theLookAt;
+ ossimPlanetLayer* theLayer;
+};
+
+class OSSIMPLANET_DLL ossimPlanetNodeReraiseCallback : public ossimPlanetNodeCallback
+{
+public:
+ ossimPlanetNodeReraiseCallback(ossimPlanetNode* node)
+ :theNode(node)
+ {
+ }
+ void setNode(ossimPlanetNode* node)
+ {
+ theNode = node;
+ }
+ ossimPlanetNode* node()
+ {
+ return theNode;
+ }
+ const ossimPlanetNode* node()const
+ {
+ return theNode;
+ }
+ virtual void propertyChanged(ossimPlanetNode* node,
+ const ossimString& name)
+ {
+ if(theNode)
+ {
+ theNode->notifyPropertyChanged(node, name);
+ }
+ }
+ virtual void destructingNode(ossimPlanetNode* node)
+ {
+ if(theNode)
+ {
+ theNode->notifyDestructing(node);
+ }
+ }
+ virtual void needsRedraw(ossimPlanetNode* /*node*/)
+ {
+ if(theNode)
+ {
+ theNode->notifyNeedsRedraw();
+ }
+ }
+ virtual void nodeAdded(osg::Node* node)
+ {
+ if(theNode)
+ {
+ theNode->notifyAddChild(node);
+ }
+ }
+ virtual void nodeRemoved(osg::Node* node)
+ {
+ if(theNode)
+ {
+ theNode->notifyRemoveChild(node);
+ }
+ }
+protected:
+ ossimPlanetNode* theNode;
+ osg::ref_ptr<ossimPlanetLookAt> theLookAt;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetNodeFactory.h b/ossimPlanet/include/ossimPlanet/ossimPlanetNodeFactory.h
new file mode 100644
index 0000000..9e4f162
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetNodeFactory.h
@@ -0,0 +1,17 @@
+#ifndef ossimPlanetNodeFactory_HEADER
+#define ossimPlanetNodeFactory_HEADER
+#include "ossimPlanetNodeFactoryBase.h"
+
+class OSSIMPLANET_DLL ossimPlanetNodeFactory : public ossimPlanetNodeFactoryBase
+{
+public:
+ ossimPlanetNodeFactory();
+ virtual ~ossimPlanetNodeFactory();
+ static ossimPlanetNodeFactory* instance();
+ virtual ossimPlanetNode* create(const ossimString& type)const;
+
+protected:
+ static ossimPlanetNodeFactory* theInstance;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetNodeFactoryBase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetNodeFactoryBase.h
new file mode 100644
index 0000000..fbdaac5
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetNodeFactoryBase.h
@@ -0,0 +1,18 @@
+#ifndef ossimPlanetNodeFactoryBase_HEADER
+#define ossimPlanetNodeFactoryBase_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+class ossimPlanetNode;
+class OSSIMPLANET_DLL ossimPlanetNodeFactoryBase : public osg::Referenced
+{
+public:
+ ossimPlanetNodeFactoryBase(){}
+ virtual ~ossimPlanetNodeFactoryBase()
+ {
+ }
+ virtual ossimPlanetNode* create(const ossimString& type)const=0;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetNodeRegistry.h b/ossimPlanet/include/ossimPlanet/ossimPlanetNodeRegistry.h
new file mode 100644
index 0000000..48fccc8
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetNodeRegistry.h
@@ -0,0 +1,30 @@
+#ifndef ossimPlanetNodeRegistry_HEADER
+#define ossimPlanetNodeRegistry_HEADER
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetNodeFactoryBase.h>
+#include <OpenThreads/ReadWriteMutex>
+#include <OpenThreads/ScopedLock>
+
+class ossimPlanetNodeRegistry
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetNodeFactoryBase> > FactoryListType;
+ ossimPlanetNodeRegistry();
+ ~ossimPlanetNodeRegistry();
+ static ossimPlanetNodeRegistry* instance();
+ void finalize();
+ ossimPlanetNode* create(const ossimString& type)const;
+ void registerFactory(ossimPlanetNodeFactoryBase* factory,
+ bool insertFrontFlag=false);
+ void unregisterFactory(const ossimPlanetNodeFactoryBase* factory);
+
+protected:
+ bool hasFactory(const ossimPlanetNodeFactoryBase* factory)const;
+
+ static ossimPlanetNodeRegistry* theInstance;
+ static ossim_uint32 theInitializeCount;
+ mutable OpenThreads::ReadWriteMutex theFactoryListMutex;
+ FactoryListType theFactoryList;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetOperation.h b/ossimPlanet/include/ossimPlanet/ossimPlanetOperation.h
new file mode 100644
index 0000000..2dc68c0
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetOperation.h
@@ -0,0 +1,422 @@
+#ifndef ossimPlanetOperation_HEADER
+#define ossimPlanetOperation_HEADER
+#include <OpenThreads/Thread>
+#include <OpenThreads/ScopedLock>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <ossimPlanet/ossimPlanetRefBlock.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimString.h>
+#include <iostream>
+
+
+class ossimPlanetOperation;
+class ossimPlanetOperationThreadQueue;
+class ossimPlanetOperationMultiThreadQueue;
+class ossimPlanetOperationQueue;
+class OSSIMPLANET_DLL ossimPlanetOperationCallback : public ossimPlanetCallback
+{
+public:
+ ossimPlanetOperationCallback(){}
+ virtual void ready(ossimPlanetOperation* /*operation*/){}
+ virtual void started(ossimPlanetOperation* /*operation*/){}
+ virtual void finished(ossimPlanetOperation* /*operation*/){}
+ virtual void canceled(ossimPlanetOperation* /*operation*/){}
+ virtual void priorityChanged(ossimPlanetOperation* /*operation*/){}
+ virtual void propertyChanged(const ossimString& /*name*/,
+ ossimPlanetOperation* /*operation*/){}
+
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetOperation : public osg::Referenced,
+ public ossimPlanetCallbackListInterface<ossimPlanetOperationCallback>
+{
+public:
+ friend class ossimPlanetOperationThreadQueue;
+ friend class ossimPlanetOperationMultiThreadQueue;
+ friend class ossimPlanetOperationQueue;
+ typedef double Priority;
+
+ enum StateType
+ {
+ READY_STATE = 0, // Specifies that the operation is ready to run
+ RUN_STATE = 1, // Specifies that the operation is currently running
+ CANCELED_STATE = 4, // Specifies that the operation was canceled
+ FINISHED_STATE = 8 // The operation ran through to completion
+ };
+ static const ossimPlanetOperation::Priority PRIORITY_HIGHEST;
+ static const ossimPlanetOperation::Priority PRIORITY_LOWEST;
+ typedef std::list<osg::ref_ptr<ossimPlanetOperation> > List;
+ ossimPlanetOperation(const ossimString& name="", const ossimString id="", ossimPlanetOperation::Priority queuePriority=0)
+ :theName(name),
+ theId(id),
+ thePriority(queuePriority),
+ theState(READY_STATE)
+ {
+ setThreadSafeRefUnref(true);
+ }
+ virtual ~ossimPlanetOperation()
+ {
+#if 0
+ if((state() == RUN_STATE)||
+ (state() == READY_STATE))
+ {
+ cancel();
+ }
+#endif
+ }
+ bool operator < (const ossimPlanetOperation& rhs)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (thePriority < rhs.thePriority);
+ }
+ bool operator < (const osg::ref_ptr<ossimPlanetOperation> rhs)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (thePriority < rhs->thePriority);
+ }
+ bool operator < (const ossimPlanetOperation* rhs)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (thePriority < rhs->thePriority);
+ }
+ bool operator > (const ossimPlanetOperation& rhs)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (thePriority > rhs.thePriority);
+ }
+ bool operator > (const ossimPlanetOperation* rhs)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (thePriority > rhs->thePriority);
+ }
+ bool operator > (const osg::ref_ptr<ossimPlanetOperation> rhs)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (thePriority > rhs->thePriority);
+ }
+ void setName(const ossimString& name)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theName = name;
+ }
+ notifyPropertyChanged("name");
+ }
+
+ const ossimString& name()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theName;
+ }
+ void setId(const ossimString& id)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theId = id;
+ }
+ notifyPropertyChanged("id");
+ }
+ const ossimString& id()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theId;
+ }
+ void setState(StateType state)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theState = state;
+ }
+ switch(state)
+ {
+ case READY_STATE:
+ {
+ notifyReady();
+ break;
+ }
+ case RUN_STATE:
+ {
+ notifyStarted();
+ break;
+ }
+ case CANCELED_STATE:
+ {
+ notifyCanceled();
+ break;
+ }
+ case FINISHED_STATE:
+ {
+ notifyFinished();
+ break;
+ }
+ }
+ }
+ bool isStopped()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return ((theState == CANCELED_STATE)||
+ (theState == FINISHED_STATE));
+ }
+ virtual StateType state()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theState;
+ }
+ virtual void release(){}
+ void addDependency(ossimPlanetOperation* operation)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theDependencyListMutex);
+ List::iterator iter = std::find(theDependencyList.begin(),
+ theDependencyList.end(),
+ operation);
+ if(iter==theDependencyList.end())
+ {
+ theDependencyList.push_back(operation);
+ }
+ }
+ void removeDependency(ossimPlanetOperation* operation)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theDependencyListMutex);
+ List::iterator iter = std::find(theDependencyList.begin(),
+ theDependencyList.end(),
+ operation);
+ if(iter!=theDependencyList.end())
+ {
+ theDependencyList.erase(iter);
+ }
+ }
+ bool hasDependency()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theDependencyListMutex);
+ return (theDependencyList.size() > 0);
+ }
+ ossimPlanetOperation::List& dependencyList()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theDependencyList;
+ }
+ const ossimPlanetOperation::List& dependencyList()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theDependencyList;
+ }
+ void setPriority(ossimPlanetOperation::Priority priority)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ thePriority = priority;
+ }
+ notifyPriorityChanged();
+ }
+ virtual ossimPlanetOperation::Priority priority()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return thePriority;
+ }
+ virtual void status(ossimString& result)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ result = theStatus;
+ }
+ virtual void setStatus(const ossimString& value)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theStatus = value;
+ }
+ notifyPropertyChanged("status");
+ }
+ /**
+ * Since you can have nested dependencies it will go until no more dependencies depend
+ * on other dependencies if the recures flag is true. If false it will just return the
+ * first one in the list.
+ */
+ osg::ref_ptr<ossimPlanetOperation> nextDependency(bool recurseFlag=true);
+ virtual void cancel()
+ {
+ setState(CANCELED_STATE);
+ }
+ OpenThreads::Mutex& runMutex(){return theRunMutex;}
+ virtual void reset()
+ {
+ setState(READY_STATE);
+ }
+ virtual void start()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRunMutex);
+ setState(RUN_STATE);
+ run();
+ if(state() == RUN_STATE) // if it wasn't canceled or set to some other state then say it has finished
+ {
+ setState(FINISHED_STATE);
+ }
+ }
+protected:
+ void notifyReady();
+ void notifyStarted();
+ void notifyFinished();
+ void notifyCanceled();
+ void notifyPriorityChanged();
+ void notifyPropertyChanged(const ossimString& name);
+ virtual void run()=0;
+
+ //mutable ossimPlanetReentrantMutex theRunMutex;
+ //mutable ossimPlanetReentrantMutex thePropertyMutex;
+ mutable OpenThreads::Mutex theRunMutex;
+ mutable OpenThreads::Mutex thePropertyMutex;
+ bool theFinishedFlag;
+ bool theCanceledFlag;
+ //mutable ossimPlanetReentrantMutex theDependencyListMutex;
+ mutable OpenThreads::Mutex theDependencyListMutex;
+ ossimPlanetOperation::List theDependencyList;
+ ossimString theName;
+ ossimString theId;
+ ossimString theStatus;
+ ossimPlanetOperation::Priority thePriority;
+ StateType theState;
+};
+
+
+class OSSIMPLANET_DLL ossimPlanetOperationQueue : public osg::Referenced
+{
+public:
+ ossimPlanetOperationQueue();
+ virtual ~ossimPlanetOperationQueue();
+ virtual void add(ossimPlanetOperation* operation, bool guaranteeUniqueFlag=true);
+ osg::ref_ptr<ossimPlanetOperation> removeByName(const ossimString& name);
+ osg::ref_ptr<ossimPlanetOperation> removeById(const ossimString& id);
+ void remove(const ossimPlanetOperation* operation);
+ void removeStoppedOperations();
+ void removeAllOperations();
+
+ virtual osg::ref_ptr<ossimPlanetOperation> nextOperation(bool blockIfEmptyFlag=true);
+ void releaseOperationsBlock();
+ bool empty()const;
+ ossim_uint32 size()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ return theOperationQueue.size();
+ }
+protected:
+ ossimPlanetOperation::List::iterator findById(const ossimString& name);
+ ossimPlanetOperation::List::iterator findByName(const ossimString& name);
+ ossimPlanetOperation::List::iterator findByPointer(const ossimPlanetOperation* operation);
+ ossimPlanetOperation::List::iterator findByNameOrPointer(const ossimPlanetOperation* operation);
+ bool hasOperation(ossimPlanetOperation* operation);
+ osg::ref_ptr<ossimPlanetRefBlock> theBlock;
+
+ // mutable ossimPlanetReentrantMutex theOperationQueueMutex;
+ mutable OpenThreads::Mutex theOperationQueueMutex;
+ ossimPlanetOperation::List theOperationQueue;
+};
+
+class OSSIMPLANET_DLL ossimPlanetOperationPriorityQueue : public ossimPlanetOperationQueue
+{
+public:
+ ossimPlanetOperationPriorityQueue();
+ virtual ~ossimPlanetOperationPriorityQueue();
+
+ virtual osg::ref_ptr<ossimPlanetOperation> nextOperation(bool blockIfEmptyFlag=true);
+protected:
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetOperationThreadQueue : public osg::Referenced,
+ public OpenThreads::Thread
+{
+public:
+ ossimPlanetOperationThreadQueue(ossimPlanetOperationQueue* opq=0);
+
+ /** Set the OperationQueue. */
+ void setOperationQueue(ossimPlanetOperationQueue* opq);
+
+ /** Get the OperationQueue. */
+ ossimPlanetOperationQueue* operationQueue() { return theOperationQueue.get(); }
+
+ /** Get the const OperationQueue. */
+ const ossimPlanetOperationQueue* operationQueue() const { return theOperationQueue.get(); }
+
+
+ /** Add operation to end of OperationQueue, this will be
+ * executed by the graphics thread once this operation gets to the head of the queue.*/
+ void add(ossimPlanetOperation* operation, bool guaranteeUniqueFlag=true);
+
+ /** Remove operation from OperationQueue.*/
+ void remove(ossimPlanetOperation* operation);
+
+ /** Remove named operation from OperationQueue.*/
+ osg::ref_ptr<ossimPlanetOperation> removeByName(const ossimString& name);
+
+ /** Remove id operation from OperationQueue.*/
+ osg::ref_ptr<ossimPlanetOperation> removeById(const ossimString& id);
+
+ /** Remove all operations from OperationQueue.*/
+ void removeAllOperations();
+
+
+ /** Get the operation currently being run.*/
+ osg::ref_ptr<ossimPlanetOperation> currentOperation() { return theCurrentOperation; }
+
+ void cancelCurrentOperation();
+ /** Run does the opertion thread run loop.*/
+ virtual void run();
+
+ void setDone(bool done);
+
+ bool done() const { return theDoneFlag; }
+
+ /** Cancel this graphics thread.*/
+ virtual int cancel();
+ bool empty()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ return theOperationQueue->empty();
+ }
+protected:
+ virtual ~ossimPlanetOperationThreadQueue();
+ virtual osg::ref_ptr<ossimPlanetOperation> nextOperation();
+
+ bool theDoneFlag;
+ mutable ossimPlanetReentrantMutex theThreadMutex;
+ osg::ref_ptr<ossimPlanetOperationQueue> theOperationQueue;
+ osg::ref_ptr<ossimPlanetOperation> theCurrentOperation;
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetOperationMultiThreadQueue : public osg::Referenced
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetOperationThreadQueue> > ThreadQueueList;
+
+ ossimPlanetOperationMultiThreadQueue(ossim_uint32 numberOfThreads=1);
+ virtual ~ossimPlanetOperationMultiThreadQueue();
+ /** Get the OperationQueue. */
+ ossimPlanetOperationQueue* operationQueue();
+
+ /** Get the const OperationQueue. */
+ const ossimPlanetOperationQueue* operationQueue() const;
+ void add(ossimPlanetOperation* operation, bool guaranteeUniqueFlag=true);
+
+ /** Remove operation from OperationQueue.*/
+ void remove(ossimPlanetOperation* operation);
+
+ /** Remove named operation from OperationQueue.*/
+ osg::ref_ptr<ossimPlanetOperation> removeByName(const ossimString& name);
+ osg::ref_ptr<ossimPlanetOperation> removeById(const ossimString& id);
+
+ /** Remove all operations from OperationQueue.*/
+ void removeAllOperations();
+ void cancelCurrentOperation();
+protected:
+ ossimPlanetReentrantMutex theThreadMutex;
+ osg::ref_ptr<ossimPlanetOperationQueue> theOperationQueue;
+ ThreadQueueList theThreadQueueList;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetOrthoFlatLandNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetOrthoFlatLandNode.h
new file mode 100644
index 0000000..f253bca
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetOrthoFlatLandNode.h
@@ -0,0 +1,26 @@
+#ifndef ossimPlanetOrthoFlatLandNode_HEADER
+#define ossimPlanetOrthoFlatLandNode_HEADER
+#include "ossimPlanetFlatLandNode.h"
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetOrthoFlatLandNode : public ossimPlanetFlatLandNode
+{
+public:
+ ossimPlanetOrthoFlatLandNode(ossim_uint32 level = 0,
+ ossim_uint32 row = 0,
+ ossim_uint32 col = 0);
+ ossimPlanetOrthoFlatLandNode(const ossimPlanetFlatLandNode& plod,const osg::CopyOp& copyop);
+ virtual ~ossimPlanetOrthoFlatLandNode();
+ virtual osg::Object* cloneType() const { return new ossimPlanetOrthoFlatLandNode(); }
+ virtual bool isSameKindAs(const osg::Object* obj) const
+ {
+ return dynamic_cast<const ossimPlanetOrthoFlatLandNode *>(obj)!=NULL;
+ }
+ virtual const char* className() const { return "OrthoFlatLandNode"; }
+ virtual const char* libraryName() const { return ""; }
+ virtual void handleCullTraversal(osg::NodeVisitor& nv);
+
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetOssimElevationDatabase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetOssimElevationDatabase.h
new file mode 100644
index 0000000..cde59d3
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetOssimElevationDatabase.h
@@ -0,0 +1,56 @@
+#ifndef ossimPlanetDtedElevationDatabase_HEADER
+#define ossimPlanetDtedElevationDatabase_HEADER
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <ossim/elevation/ossimGeneralRasterElevationDatabase.h>
+#include <ossim/elevation/ossimImageElevationDatabase.h>
+#include <osg/Timer>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/elevation/ossimElevationDatabase.h>
+
+class OSSIMPLANET_DLL ossimPlanetOssimElevationDatabase : public ossimPlanetElevationDatabase
+{
+public:
+ ossimPlanetOssimElevationDatabase();
+ ossimPlanetOssimElevationDatabase(const ossimPlanetOssimElevationDatabase& src);
+ virtual ~ossimPlanetOssimElevationDatabase();
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ virtual void resetStats()const;
+
+ virtual ossimPlanetTextureLayerStateCode open(const std::string& location);
+ virtual void setDatabase(ossimElevationDatabase* database)
+ {
+ m_database = database;
+ m_cellDatabaseFlag = ((!dynamic_cast<ossimGeneralRasterElevationDatabase*>(database) &&
+ !dynamic_cast<ossimImageElevationDatabase*>(database))&&
+ ((dynamic_cast<ossimElevationCellDatabase*>(database) != 0)));
+ updateExtents();
+ }
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 /* level */,
+ ossim_uint64 /* row */,
+ ossim_uint64 /* col */,
+ const ossimPlanetGridUtility& /* utility */)
+ {
+ return 0;
+ }
+protected:
+ virtual osg::ref_ptr<ossimPlanetImage> getTextureCellDatabase(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding=0);
+ bool m_cellDatabaseFlag;
+ ossimRefPtr<ossimElevationDatabase> m_database;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetOssimImage.h b/ossimPlanet/include/ossimPlanet/ossimPlanetOssimImage.h
new file mode 100644
index 0000000..e5aadfd
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetOssimImage.h
@@ -0,0 +1,21 @@
+#ifndef ossimPlanetOssimImage_HEADER
+#define ossimPlanetOssimImage_HEADER
+#include <iostream>
+#include "ossimPlanetExport.h"
+#include <osg/Referenced>
+#include <ossim/imaging/ossimImageHandler.h>
+
+class ossimPlanetImage;
+class OSSIMPLANET_DLL ossimPlanetOssimImage : public osg::Referenced
+{
+public:
+ ossimPlanetOssimImage();
+ virtual ~ossimPlanetOssimImage();
+ bool loadFile(const std::string& inputFile,
+ ossimPlanetImage& image);
+
+protected:
+ ossimRefPtr<ossimImageHandler> theHandler;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetOssimImageLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetOssimImageLayer.h
new file mode 100644
index 0000000..a5fe5c8
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetOssimImageLayer.h
@@ -0,0 +1,370 @@
+#ifndef ossimPlanetOssimImageLayer_HEADER
+#define ossimPlanetOssimImageLayer_HEADER
+#include "ossimPlanetTextureLayer.h"
+#include <osg/Referenced>
+#include "ossimPlanetId.h"
+#include "ossimPlanetExport.h"
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimImageRenderer.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/imaging/ossimGeoAnnotationSource.h>
+#include <ossim/imaging/ossimGeoAnnotationPolyObject.h>
+#include <ossim/imaging/ossimHistogramRemapper.h>
+#include <ossim/imaging/ossimRectangleCutFilter.h>
+#include <ossim/elevation/ossimElevManager.h>
+#include <ossim/projection/ossimLlxyProjection.h>
+#include <queue>
+class OSSIMPLANET_DLL ossimPlanetOssimImageLayer : public ossimPlanetTextureLayer
+{
+public:
+ ossimPlanetOssimImageLayer();
+ ossimPlanetOssimImageLayer(const ossimPlanetOssimImageLayer& src);
+ ossimPlanetTextureLayerStateCode openImage(const ossimFilename& filename, ossim_int32 entryIdx = -1);
+ ossimPlanetTextureLayerStateCode setCurrentEntry(ossim_int32 idx);
+ ossim_uint32 getNumberOfEntries()const;
+ void setOverviewFile(const ossimFilename& overviewFile);
+ void setHistogramFile(const ossimFilename& histogram);
+ void setHistogramStretchMode(const ossimString& mode);
+ void setHistogramStretchEnableFlag(bool flag);
+ bool histogramStretchEnableFlag()const;
+ ossimString histogramStretchMode()const;
+ void getHistogramStretchModes(std::vector<ossimString>& modes);
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimString getClassName()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ virtual void resetStats()const;
+ ossimScalarType scalarType()const;
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+ ossimPlanetTextureLayerStateCode setHandler(ossimRefPtr<ossimImageHandler> handler);
+ ossimRefPtr<ossimImageHandler> getHandler();
+ const ossimRefPtr<ossimImageHandler> getHandler()const;
+
+ virtual double getApproximateHypotneusLength()const;
+ virtual void getCenterLatLonLength(double& centerLat,
+ double& centerLon,
+ double& length)const;
+ void setFilterType(const ossimString& filterType);
+
+ bool isMultiEntry()const;
+
+ virtual bool buildOverview();
+
+ osg::ref_ptr<ossimPlanetTextureLayer> groupAllEntries();
+ virtual void getMetadata(ossimRefPtr<ossimXmlNode> metadata)const;
+
+ virtual ossimRefPtr<ossimXmlNode> saveXml(bool recurseFlag=true)const;
+ virtual bool loadXml(ossimRefPtr<ossimXmlNode> node);
+
+protected:
+ struct ResamplePoint
+ {
+ public:
+ friend ostream& operator <<(ostream& out, const ResamplePoint& point)
+ {
+ out << point.theGlobalNdcPoint << "\n"
+ << point.theModelPoint << "\n"
+ << point.theImagePoint << "\n"
+ << point.theTileImagePoint << "\n"
+ << point.theDecimation << "\n"
+ << point.theResolutionLevel;
+
+ return out;
+ }
+ ResamplePoint(){}
+ ResamplePoint(const ossimPlanetGrid::GridPoint& globalPoint,
+ const ossimPlanetGrid::ModelPoint& modelPt,
+ const ossimDpt& imgPt,
+ const ossimDpt& tileImgPt,
+ const ossimDpt& decimation,
+ ossim_uint32 rLevel)
+ :theGlobalNdcPoint(globalPoint),
+ theModelPoint(modelPt),
+ theImagePoint(imgPt),
+ theTileImagePoint(tileImgPt),
+ theDecimation(decimation),
+ theResolutionLevel(rLevel)
+ {}
+ ossimPlanetGrid::GridPoint theGlobalNdcPoint;
+ ossimPlanetGrid::ModelPoint theModelPoint;
+ ossimDpt theImagePoint;
+ ossimDpt theTileImagePoint;
+ ossimDpt theDecimation;
+ ossim_uint32 theResolutionLevel;
+ };
+ struct ResampleCorner
+ {
+ public:
+ friend std::ostream& operator <<(std::ostream& out, const ResampleCorner& corners)
+ {
+ out << corners.theP1 << "\n" << corners.theP2 << "\n"
+ << corners.theP3 << "\n" << corners.theP4;
+
+ return out;
+ }
+ ResampleCorner(){}
+ ResampleCorner(const ResamplePoint& p1,
+ const ResamplePoint& p2,
+ const ResamplePoint& p3,
+ const ResamplePoint& p4)
+ :theP1(p1),
+ theP2(p2),
+ theP3(p3),
+ theP4(p4)
+ {}
+ bool canBilinearInterpolate(ossimProjection* proj,
+ const ossimPlanetGrid& grid)const
+ {
+ ossimPlanetGrid::GridPoint globalGridCenter(theP1.theGlobalNdcPoint.face(),
+ (theP1.theGlobalNdcPoint.x()+
+ theP2.theGlobalNdcPoint.x()+
+ theP3.theGlobalNdcPoint.x()+
+ theP4.theGlobalNdcPoint.x())*.25,
+ (theP1.theGlobalNdcPoint.y()+
+ theP2.theGlobalNdcPoint.y()+
+ theP3.theGlobalNdcPoint.y()+
+ theP4.theGlobalNdcPoint.y())*.25);
+ ossimDpt inputImageCenter((theP1.theImagePoint.x +
+ theP2.theImagePoint.x +
+ theP3.theImagePoint.x +
+ theP4.theImagePoint.x)*.25,
+ (theP1.theImagePoint.y +
+ theP2.theImagePoint.y +
+ theP3.theImagePoint.y +
+ theP4.theImagePoint.y)*.25);
+
+
+ ossimPlanetGrid::ModelPoint centerModel;
+ ossimDpt centerImageTest;
+ grid.globalGridToModel(globalGridCenter, centerModel);
+ ossimGpt gpt(centerModel.y(),
+ centerModel.x());
+ if(proj->isAffectedByElevation())
+ {
+ gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+ }
+ proj->worldToLineSample(gpt,
+ centerImageTest);
+ double errorMetric = (inputImageCenter-centerImageTest).length();
+
+ //std::cout << "face == " << theP1.theGlobalNdcPoint.face() << std::endl;
+ //std::cout << "ERROR == " << errorMetric << std::endl;
+ return (errorMetric<1.0);
+ }
+ ossim_uint32 tileWidth()const
+ {
+ return (theP1.theTileImagePoint - theP2.theTileImagePoint).length();
+ }
+ ossim_uint32 tileHeight()const
+ {
+ return (theP1.theTileImagePoint - theP4.theTileImagePoint).length();
+ }
+ ossimDrect boundingInputImageRect()const
+ {
+ return ossimDrect(ossim::min(theP1.theImagePoint.x,
+ ossim::min(theP2.theImagePoint.x,
+ ossim::min(theP3.theImagePoint.x, theP4.theImagePoint.x))),
+ ossim::max(theP1.theImagePoint.y,
+ ossim::max(theP2.theImagePoint.y,
+ ossim::max(theP3.theImagePoint.y, theP4.theImagePoint.y))),
+ ossim::max(theP1.theImagePoint.x,
+ ossim::max(theP2.theImagePoint.x,
+ ossim::max(theP3.theImagePoint.x, theP4.theImagePoint.x))),
+ ossim::min(theP1.theImagePoint.y,
+ ossim::min(theP2.theImagePoint.y,
+ ossim::min(theP3.theImagePoint.y, theP4.theImagePoint.y))),
+ OSSIM_RIGHT_HANDED);
+ }
+
+ ossimDrect boundingInputImageRect(const ossimDpt& decimation)const
+ {
+ return boundingInputImageRect()*decimation;
+ }
+ void split(ossimProjection* proj,
+ const ossimPlanetGrid& grid,
+ ResampleCorner& bound1,
+ ResampleCorner& bound2,
+ ResampleCorner& bound3,
+ ResampleCorner& bound4)
+ {
+ // use parametric to split along each line going in
+ // counter clockwise for the edges.
+ //
+
+ //
+ ossimPlanetGrid::ModelPoint model;
+ ResamplePoint centerP1P2;
+ ResamplePoint centerP2P3;
+ ResamplePoint centerP3P4;
+ ResamplePoint centerP4P1;
+ ResamplePoint centerPt;
+
+ centerP1P2.theGlobalNdcPoint.theFace = theP1.theGlobalNdcPoint.theFace;
+ centerP2P3.theGlobalNdcPoint.theFace = theP1.theGlobalNdcPoint.theFace;
+ centerP3P4.theGlobalNdcPoint.theFace = theP1.theGlobalNdcPoint.theFace;
+ centerP4P1.theGlobalNdcPoint.theFace = theP1.theGlobalNdcPoint.theFace;
+ centerPt.theGlobalNdcPoint.theFace = theP1.theGlobalNdcPoint.theFace;
+
+
+
+ centerP1P2.theGlobalNdcPoint.setX((theP2.theGlobalNdcPoint.x()+theP1.theGlobalNdcPoint.x())*.5);
+ centerP1P2.theGlobalNdcPoint.setY(theP1.theGlobalNdcPoint.y());
+ centerP1P2.theTileImagePoint.x = (ossim_int32)((theP2.theTileImagePoint.x+theP1.theTileImagePoint.x)*.5);
+ centerP1P2.theTileImagePoint.y = (ossim_int32)theP2.theTileImagePoint.y;
+ centerP1P2.theDecimation = theP1.theDecimation;
+ centerP1P2.theResolutionLevel = theP1.theResolutionLevel;
+ grid.globalGridToModel(centerP1P2.theGlobalNdcPoint, model);
+ ossimGpt gpt(model.y(),
+ model.x());
+
+ if(proj->isAffectedByElevation())
+ {
+ gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+ }
+ //std::cout << "class = " << proj->getClassName() << std::endl;
+ //std::cout << "gpt = " << gpt << std::endl;
+ proj->worldToLineSample(gpt,
+ centerP1P2.theImagePoint);
+
+ centerP2P3.theGlobalNdcPoint.setX(theP2.theGlobalNdcPoint.x());
+ centerP2P3.theGlobalNdcPoint.setY((theP3.theGlobalNdcPoint.y()+theP2.theGlobalNdcPoint.y())*.5);
+ centerP2P3.theTileImagePoint.x = theP2.theTileImagePoint.x;
+ centerP2P3.theTileImagePoint.y = (ossim_int32)((theP2.theTileImagePoint.y+theP3.theTileImagePoint.y)*.5);
+ centerP2P3.theDecimation = theP2.theDecimation;
+ centerP2P3.theResolutionLevel = theP2.theResolutionLevel;
+ grid.globalGridToModel(centerP2P3.theGlobalNdcPoint, model);
+ gpt = ossimGpt(model.y(),
+ model.x());
+ if(proj->isAffectedByElevation())
+ {
+ gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+ }
+ proj->worldToLineSample(gpt,
+ centerP2P3.theImagePoint);
+
+
+ centerP3P4.theGlobalNdcPoint.setX((theP4.theGlobalNdcPoint.x()+theP3.theGlobalNdcPoint.x())*.5);
+ centerP3P4.theGlobalNdcPoint.setY(theP3.theGlobalNdcPoint.y());
+ centerP3P4.theTileImagePoint.x = (ossim_int32)((theP3.theTileImagePoint.x+theP4.theTileImagePoint.x)*.5);
+ centerP3P4.theTileImagePoint.y = theP3.theTileImagePoint.y;
+ centerP3P4.theDecimation = theP3.theDecimation;
+ centerP3P4.theResolutionLevel = theP3.theResolutionLevel;
+ grid.globalGridToModel(centerP3P4.theGlobalNdcPoint, model);
+ gpt = ossimGpt(model.y(),
+ model.x());
+ if(proj->isAffectedByElevation())
+ {
+ gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+ }
+ proj->worldToLineSample(gpt,
+ centerP3P4.theImagePoint);
+
+
+ centerP4P1.theGlobalNdcPoint.setX(theP1.theGlobalNdcPoint.x());
+ centerP4P1.theGlobalNdcPoint.setY((theP1.theGlobalNdcPoint.y()+theP4.theGlobalNdcPoint.y())*.5);
+ centerP4P1.theTileImagePoint.x = theP1.theTileImagePoint.x;
+ centerP4P1.theTileImagePoint.y = (ossim_int32)((theP1.theTileImagePoint.y + theP4.theTileImagePoint.y)*.5);
+ centerP4P1.theDecimation = theP4.theDecimation;
+ centerP4P1.theResolutionLevel = theP4.theResolutionLevel;
+ grid.globalGridToModel(centerP4P1.theGlobalNdcPoint, model);
+ gpt = ossimGpt(model.y(),
+ model.x());
+ if(proj->isAffectedByElevation())
+ {
+ gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+ }
+ proj->worldToLineSample(gpt,
+ centerP4P1.theImagePoint);
+
+ centerPt.theGlobalNdcPoint.setX(centerP1P2.theGlobalNdcPoint.x());
+ centerPt.theGlobalNdcPoint.setY(centerP4P1.theGlobalNdcPoint.y());
+ centerPt.theTileImagePoint.x = centerP1P2.theTileImagePoint.x;
+ centerPt.theTileImagePoint.y = centerP4P1.theTileImagePoint.y;
+ grid.globalGridToModel(centerPt.theGlobalNdcPoint, model);
+ gpt = ossimGpt(model.y(),
+ model.x());
+ if(proj->isAffectedByElevation())
+ {
+ gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+ }
+ proj->worldToLineSample(gpt,
+ centerPt.theImagePoint);
+ centerPt.theDecimation = theP4.theDecimation;
+ centerPt.theResolutionLevel = theP4.theResolutionLevel;
+
+ bound1.theP1 = theP1;
+ bound1.theP2 = centerP1P2;
+ bound1.theP3 = centerPt;
+ bound1.theP4 = centerP4P1;
+
+ bound2.theP1 = centerP1P2;
+ bound2.theP2 = theP2;
+ bound2.theP3 = centerP2P3;
+ bound2.theP4 = centerPt;
+
+ bound3.theP1 = centerPt;
+ bound3.theP2 = centerP2P3;
+ bound3.theP3 = theP3;
+ bound3.theP4 = centerP3P4;
+
+ bound4.theP1 = centerP4P1;
+ bound4.theP2 = centerPt;
+ bound4.theP3 = centerP3P4;
+ bound4.theP4 = theP4;
+ }
+ ResamplePoint theP1;
+ ResamplePoint theP2;
+ ResamplePoint theP3;
+ ResamplePoint theP4;
+ };
+ typedef std::queue<ResampleCorner> ResampleCorners;
+ virtual ~ossimPlanetOssimImageLayer();
+ void clearChains();
+ virtual ossimPlanetTextureLayerStateCode updateExtentsNoMutex();
+ ossimPlanetTextureLayerStateCode buildChain();
+
+ void initializeResamplePoints(const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_uint32 tileWidth,
+ ossim_uint32 tileHeight,
+ ResampleCorners& corners);
+
+ ossimFilename theFilename;
+ ossimFilename theOverviewFile;
+ ossimFilename theHistogramFile;
+ ossimRectangleCutFilter* theCut;
+ mutable ossimRefPtr<ossimImageHandler> theSource;
+ ossimRefPtr<ossimImageRenderer> theRenderer;
+ ossimViewInterface* theViewInterface;
+ ossimHistogramRemapper* theHistogramRemapper;
+ ossimHistogramRemapper::StretchMode theHistogramStretchMode;
+ bool theHistogramStretchEnableFlag;
+ std::vector<ossimRefPtr<ossimImageSource> > theChain;
+ std::vector<ossimRefPtr<ossimImageSource> > theImageSpaceChain;
+ // ossimRefPtr<ossimEquDistCylProjection> theProjection;
+ ossimRefPtr<ossimImageGeometry> theImageGeometry;
+ ossimRefPtr<ossimMapProjection> theProjection;
+ ossimRefPtr<ossimProjection> theInputProjection;
+ mutable double theCenterLat;
+ mutable double theCenterLon;
+ mutable double theLength; // approximate length in meters of the diagonal image
+ mutable OpenThreads::Mutex theOssimImageLayerMutex;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPagedLandLod.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPagedLandLod.h
new file mode 100644
index 0000000..395fa7f
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPagedLandLod.h
@@ -0,0 +1,199 @@
+#ifndef ossimPlanetPagedLandLod_HEADER
+#define ossimPlanetPagedLandLod_HEADER
+#include <osg/NodeVisitor>
+#include <osg/Group>
+#include <osg/PagedLOD>
+#include <osg/MatrixTransform>
+#include <osg/Geometry>
+#include <OpenThreads/ScopedLock>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include "ossimPlanet/ossimPlanetBoundingBox.h"
+#include <ossimPlanet/ossimPlanetLandTextureRequest.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetPagedLandLodCullNode : public osg::MatrixTransform
+{
+public:
+ ossimPlanetPagedLandLodCullNode():
+ osg::MatrixTransform(),
+ theCulledFlag(false)
+ {}
+ ossimPlanetPagedLandLodCullNode(osg::ref_ptr<ossimPlanetBoundingBox> boundingBox,
+ bool useClusterCulling,
+ const osg::Vec3d& clusterCullingControlPoint,
+ const osg::Vec3d& clusterCullingNormal,
+ double clusterCullingDeviation,
+ double clusterCullingRadius):
+ osg::MatrixTransform(),
+ theCulledFlag(false),
+ theBoundingBox(boundingBox),
+ theUseClusterCulling(useClusterCulling),
+ theClusterCullingControlPoint(clusterCullingControlPoint),
+ theClusterCullingNormal(clusterCullingNormal),
+ theClusterCullingDeviation(clusterCullingDeviation),
+ theClusterCullingRadius(clusterCullingRadius)
+ {}
+ ossimPlanetPagedLandLodCullNode(const ossimPlanetPagedLandLodCullNode& src):
+ osg::MatrixTransform(src),
+ theCulledFlag(src.theCulledFlag),
+ theBoundingBox(new ossimPlanetBoundingBox(*src.theBoundingBox)),
+ theUseClusterCulling(src.theUseClusterCulling),
+ theClusterCullingControlPoint(src.theClusterCullingControlPoint),
+ theClusterCullingNormal(src.theClusterCullingNormal),
+ theClusterCullingDeviation(src.theClusterCullingDeviation),
+ theClusterCullingRadius(src.theClusterCullingRadius)
+ {
+ }
+ void setBoundingBox(osg::ref_ptr<ossimPlanetBoundingBox> box)
+ {
+ theBoundingBox = box.get();
+ }
+
+ const ossimPlanetBoundingBox* boundingBox()const
+ {
+ return theBoundingBox.get();
+ }
+ double eyeDistance()const
+ {
+ return theEyeDistance;
+ }
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ bool isCulled()const
+ {
+ return theCulledFlag;
+ }
+
+protected:
+ bool theCulledFlag;
+ osg::ref_ptr<ossimPlanetBoundingBox> theBoundingBox;
+ bool theUseClusterCulling;
+ osg::Vec3d theClusterCullingControlPoint;
+ osg::Vec3d theClusterCullingNormal;
+ double theClusterCullingDeviation;
+ double theClusterCullingRadius;
+
+ double theEyeDistance;
+};
+
+class ossimPlanetLandCullCallback;
+class ossimPlanetLand;
+class OSSIMPLANET_EXPORT ossimPlanetPagedLandLod : public osg::Group//public osg::PagedLOD
+{
+public:
+
+ friend class ossimPlanetLandCullCallback;
+ friend class ossimPlanetPagedLandLodUpdateCallback;
+ friend class ossimPlanetLandReaderWriter;
+ friend class ossimPlanetPagedLandLodClearPointers;
+
+ virtual osg::Object* cloneType() const { return new ossimPlanetPagedLandLod(); }
+ virtual osg::Object* clone(const osg::CopyOp& copyop) const
+ {
+ return new ossimPlanetPagedLandLod(*this,copyop);
+ }
+ virtual bool isSameKindAs(const osg::Object* obj) const
+ {
+ return dynamic_cast<const ossimPlanetPagedLandLod *>(obj)!=0;
+ }
+ virtual const char* className() const { return "PlanetPagedLandLod"; }
+ virtual const char* libraryName() const { return ""; }
+ ossimPlanetPagedLandLod(ossim_uint32 level=0,
+ ossim_uint32 row=0,
+ ossim_uint32 col=0,
+ const std::string& requestName="");
+ ossimPlanetPagedLandLod(const ossimPlanetPagedLandLod& src,
+ const osg::CopyOp& copyop);
+ virtual ~ossimPlanetPagedLandLod();
+ void setRequestName(ossim_uint32 idx,
+ const std::string& name)
+ {
+ theRequestNameList[idx] = name;
+ }
+ std::string getRequestName(ossim_uint32 idx)const
+ {
+ return theRequestNameList[idx];
+ }
+ bool getRemoveChildrenFlag()const
+ {
+ return theRemoveChildrenFlag;
+ }
+ bool getCulledFlag()const
+ {
+ return theCulledFlag;
+ }
+
+ virtual bool addChild( Node *child );
+
+ ossim_uint32 getLevel()const
+ {
+ return theLevel;
+ }
+ ossim_uint32 getRow()const
+ {
+ return theRow;
+ }
+ ossim_uint32 getCol()const
+ {
+ return theCol;
+ }
+ bool isLeaf()const
+ {
+ return (getNumChildren() != 5);
+ }
+ bool hasCulledChildren()const;
+ bool areAllChildrenCulled(bool applyToAddedChildrenOnly=false)const;
+ bool areAllChildrenLeaves()const;
+ OpenThreads::Mutex& mutex()const
+ {
+ return theMutex;
+ }
+
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ void setRefreshType(ossimPlanetLandRefreshType refreshType);
+ ossimPlanetLandRefreshType refreshType()const;
+protected:
+ ossimPlanetLand* landLayer();
+ const ossimPlanetLand* landLayer()const;
+
+ osg::ref_ptr<osg::Geode> theGeode;
+ ossim_uint32 theLevel;
+ ossim_uint32 theRow;
+ ossim_uint32 theCol;
+/* osg::ref_ptr<ossimPlanetBoundingBox> theBoundingBox; */
+ std::vector<std::string> theRequestNameList;
+ osg::ref_ptr<osg::Referenced> theRequestRefChildList[4];
+ osg::ref_ptr<osg::Referenced> theRequestRef;
+ bool theCulledFlag;
+ bool theRemoveChildrenFlag;
+ ossimPlanetLandRefreshType theRefreshType;
+ mutable ossimPlanetReentrantMutex theMutex;
+ mutable ossimPlanetReentrantMutex thePagedLodListMutex;
+ mutable ossimPlanetReentrantMutex theChildCullNodeListMutex;
+ mutable ossimPlanetReentrantMutex theTextureRequestMutex;
+ osg::ref_ptr<ossimPlanetPagedLandLodCullNode> theCullNode;
+
+/* osg::Node* theTransform; */
+ ossim_uint32 theMaxLevel;
+ osg::Vec3d theCenterPoint;
+ osg::Vec3d theUlPoint;
+ osg::Vec3d theUrPoint;
+ osg::Vec3d theLrPoint;
+ osg::Vec3d theLlPoint;
+ osg::Vec3d theCenterNormal;
+ osg::Vec3d theUlNormal;
+ osg::Vec3d theUrNormal;
+ osg::Vec3d theLrNormal;
+ osg::Vec3d theLlNormal;
+
+
+// lists to add during update calls
+ //
+ std::vector<osg::ref_ptr<ossimPlanetPagedLandLod> > thePagedLodList;
+ std::vector<osg::ref_ptr<ossimPlanetPagedLandLodCullNode> > theChildCullNodeList;
+ osg::ref_ptr<ossimPlanetLandTextureRequest> theTextureRequest;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPagedLandLodRefreshType.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPagedLandLodRefreshType.h
new file mode 100644
index 0000000..615953b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPagedLandLodRefreshType.h
@@ -0,0 +1,16 @@
+#ifndef ossimPlanetPagedLandLodRefreshType_HEADER
+#define ossimPlanetPagedLandLodRefreshType_HEADER
+
+// Been moved to ossimPlanetConstants.h
+// This file is deprecated
+#error File header depcricated, plaese use ossimPlanet/ossimPlanetConstants.h
+
+/* enum ossimPlanetPagedLandLodRefreshType */
+/* { */
+/* ossimPlanetPagedLandLodRefreshType_NONE = 0, */
+/* ossimPlanetPagedLandLodRefreshType_TEXTURE = 1, */
+/* ossimPlanetPagedLandLodRefreshType_GEOM = 2, */
+/* ossimPlanetPagedLandLodRefreshType_PRUNE = 3, */
+/* }; */
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPagedRequestNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPagedRequestNode.h
new file mode 100644
index 0000000..365e7f1
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPagedRequestNode.h
@@ -0,0 +1,70 @@
+#ifndef ossimPlanetPagedRequestNode_HEADER
+#define ossimPlanetPagedRequestNode_HEADER
+#include <osg/Node>
+#include <osg/ref_ptr>
+#include <osg/Texture2D>
+#include <ossim/base/ossimConstants.h>
+#include <iostream>
+#include "ossimPlanetElevationGrid.h"
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetPagedRequestNode : public osg::Node
+{
+public:
+ ossimPlanetPagedRequestNode(ossim_uint32 level=0,
+ ossim_uint32 row=0,
+ ossim_uint32 col=0,
+ osg::ref_ptr<osg::Texture2D> texture=0)
+ :osg::Node(),
+ theLevel(level),
+ theRow(row),
+ theCol(col),
+ theTexture(texture)
+ {
+ }
+ virtual ~ossimPlanetPagedRequestNode()
+ {
+ }
+ osg::ref_ptr<osg::Texture2D> getTexture()
+ {
+ return theTexture;
+ }
+ osg::ref_ptr<ossimPlanetElevationGrid> getElevation()
+ {
+ return theElevationGrid;
+ }
+ const osg::ref_ptr<ossimPlanetElevationGrid> getElevation()const
+ {
+ return theElevationGrid;
+ }
+ void setElevation(osg::ref_ptr<ossimPlanetElevationGrid> elevationGrid)
+ {
+ theElevationGrid = elevationGrid;
+ }
+ void setTexture(osg::ref_ptr<osg::Texture2D> texture)
+ {
+ theTexture = texture;
+ }
+ ossim_uint32 getLevel()const
+ {
+ return theLevel;
+ }
+ ossim_uint32 getRow()const
+ {
+ return theRow;
+ }
+ ossim_uint32 getCol()const
+ {
+ return theCol;
+ }
+
+
+protected:
+ ossim_uint32 theLevel;
+ ossim_uint32 theRow;
+ ossim_uint32 theCol;
+ osg::ref_ptr<osg::Texture2D> theTexture;
+ osg::ref_ptr<ossimPlanetElevationGrid> theElevationGrid;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPlaneGrid.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPlaneGrid.h
new file mode 100644
index 0000000..582ce21
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPlaneGrid.h
@@ -0,0 +1,28 @@
+#ifndef ossimPlanetPlaneGrid_HEADER
+#define ossimPlanetPlaneGrid_HEADER
+#include <ossimPlanet/ossimPlanetGridUtility.h>
+
+class OSSIMPLANET_DLL ossimPlanetPlaneGrid : public ossimPlanetGridUtility
+{
+public:
+ ossimPlanetPlaneGrid(ossim_uint32 tileWidth = 256,
+ ossim_uint32 tileHeight = 256)
+ :ossimPlanetGridUtility(tileWidth, tileHeight)
+ {
+ }
+ virtual ossim_uint32 getNumberOfFaces()const;
+ virtual void getPixelScale(double& dx,
+ double& dy,
+ ossimUnitType& pixelScaleUnits,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const;
+
+ virtual void getGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ const osg::Vec3d& latLon)const;
+
+ virtual void getLatLon(osg::Vec3d& latLon,
+ const ossimPlanetGridUtility::GridPoint& gridPoint)const;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPointModel.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPointModel.h
new file mode 100644
index 0000000..0435068
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPointModel.h
@@ -0,0 +1,150 @@
+#ifndef ossimPlanetPointModel_HEADER
+#define ossimPlanetPointModel_HEADER
+#include <ossimPlanet/ossimPlanetAnnotationLayerNode.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetLsrSpaceTransform.h>
+
+/**
+ * This will be the root class to handle all point based models.
+ * Typically this may pertain to buildings or other 3-D
+ * point models. This will also own an ossimLsrSpaceTransform that
+ * allows one to talk to the Matrix transform in a common Euler orientation
+ * and lat lon altitude placement and scale settings. The Lsr stands for Local Space
+ * Reference and mirrors the conepts in the ossim core engine.
+ *
+ * Caveat: If the setMatrix is called on a MatrixTransform which is a base of
+ * ossimPlanetLsrSpaceTransform then it will not sync the euler and lat lon paramters
+ * until the next call to computeBound. Note setMatrix will dirty the bound. So if you want immediate
+ * sync to occurr then you must manually say getBound immediately after a setMatrix. This should
+ * force a recompute.
+ *
+ *
+ * <pre>
+ * EXAMPLE USAGE:
+ * We will assume we have an annotation layer defined in ossimPlanetViewer and will access through the Viewer
+ *
+ * osg::ref_ptr<ossimPlanetPointModel> pointModel = new ossimPlanetPointModel;
+ * // adding the object should automatically setup the pointers for model and layer on the Node.
+ * viewer->addAnnotation(pointModel.get());
+ *
+ * // node is some local 3-D comdel that you wish to posistion.
+ * pointModel->setNode(node);
+ *
+ * // set the point at 25 degrees lat, -120 degrees lon and 5000 meters above the ellipsoid. Note this call
+ * // assumes ellipsoidal height. Use mean sea level call for heights above the geoidal egm grid.
+ * pointModel->lsrSpace()->setLatLonAltitude(osg::Vec3d(25.0, -120, 5000));
+ *
+ *
+ * </pre>
+ */
+class OSSIMPLANET_DLL ossimPlanetPointModel : public ossimPlanetAnnotationLayerNode
+{
+public:
+ class LsrSpaceCallback : public ossimPlanetLsrSpaceTransformCallback
+ {
+ public:
+ LsrSpaceCallback(ossimPlanetPointModel* model)
+ :thePointModel(model)
+ {
+ }
+ virtual void lsrSpaceChanged(ossimPlanetLsrSpaceTransform* /*lsrSpace*/)
+ {
+ if(thePointModel)
+ {
+ thePointModel->dirtyBound();
+ thePointModel->setRedrawFlag(true);
+ }
+ }
+ protected:
+ ossimPlanetPointModel* thePointModel;
+ };
+ ossimPlanetPointModel();
+ virtual ~ossimPlanetPointModel();
+
+ /**
+ * For now we will do nothing for the update. This is reserved for future background operations on a node
+ * to update itself. It iwll be up to the node's responsibility to update only its dirty components. Note
+ * this is not synched to the Update Visitor but this virtual method is an interface to an UpdateOperation.
+ */
+ virtual void update(){}
+
+
+ /**
+ * It will keep in sync during the update stage the node this point model is
+ * controlling with a LsrSpace transform.
+ *
+ * @param nv Node visitor base for all visitors.
+ */
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ /**
+ * This will be the point model controlled by this class.
+ * During the update traversal it will be aded to the ossimPlanetLsrSpaceTransform
+ *
+ * @param node This node is assumed to be relative values from the LsrSpaceTransform
+ */
+ void setNode(osg::Node* node);
+
+ /**
+ * @return Returns a constant reference to a Local Space Reference for this point model.
+ */
+ const ossimPlanetLsrSpaceTransform* lsrSpace()const{return theLsrSpaceTransform.get();}
+
+ /**
+ * @return Returns a reference to a Local Space Reference for this point model.
+ */
+ ossimPlanetLsrSpaceTransform* lsrSpace(){return theLsrSpaceTransform.get();}
+
+ /**
+ * This Will copy the LSR parameters.
+ *
+ * @param lsr The Local Space Reference to copy the parameters from.
+ */
+ void copyLsrSpaceParameters(const ossimPlanetLsrSpaceTransform& lsr);
+
+ /**
+ * overrides set layer so we can pass the model immediatley to the Local Space Reference
+ * transform.
+ *
+ * @param layer The ossimPlanetLayer we are part of.
+ */
+ virtual void setLayer(ossimPlanetLayer* layer);
+
+ virtual osg::BoundingSphere computeBound()const
+ {
+ if(theLsrSpaceTransform.valid())
+ {
+ return theLsrSpaceTransform->computeBound();
+ }
+ return osg::BoundingSphere(osg::Vec3d(0.0,0.0,0.0), -1);
+ }
+protected:
+ /**
+ * Checks if the required pointers are set. Will see if layer and model exist.
+ */
+ bool checkPointers();
+
+ /**
+ * General mutex to sync access to the parameters with other threads.
+ */
+ ossimPlanetReentrantMutex thePointModelPropertyMutex;
+
+ /**
+ * The Local space node will be added to the LsrSpace transform.
+ */
+ osg::ref_ptr<ossimPlanetLsrSpaceTransform> theLsrSpaceTransform;
+
+ /**
+ * Indication that we need to update the matrix transform to encapsulate the node.
+ */
+ bool theNodeChangedFlag;
+
+ /**
+ * Direct access to the node that is a child of MatrixTransform.
+ */
+ osg::ref_ptr<osg::Node> theNode;
+
+ osg::ref_ptr<LsrSpaceCallback> theLsrSpaceCallback;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPredatorVideoLayerNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPredatorVideoLayerNode.h
new file mode 100644
index 0000000..c403e4c
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPredatorVideoLayerNode.h
@@ -0,0 +1,264 @@
+#ifndef ossimPlanetPredatorVideoLayerNode_HEADER
+#define ossimPlanetPredatorVideoLayerNode_HEADER
+#include "ossimPlanetVideoLayerNode.h"
+#include "ossimPlanetIconGeom.h"
+#include "ossimPlanetRefBlock.h"
+#include <ossimPredator/ossimPredatorVideo.h>
+#include "ossimPlanetBillboardIcon.h"
+#include "ossimPlanetGeoRefModel.h"
+#include <osg/ImageStream>
+#include <osg/Timer>
+#include <osg/Viewport>
+#include <osg/CameraNode>
+#include <osg/MatrixTransform>
+#include <osg/Geode>
+#include <OpenThreads/Thread>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <OpenThreads/ScopedLock>
+#include <OpenThreads/Block>
+#include <osg/Switch>
+
+class OSSIMPLANET_DLL ossimPlanetFFMpegImageStream : public osg::ImageStream, public OpenThreads::Thread
+{
+public:
+
+ class OSSIMPLANET_DLL CoordinateInfo : public osg::Referenced
+ {
+ public:
+ CoordinateInfo()
+ :theFrameCenterLlhValidFlag(true),
+ theSensorPositionLlhValidFlag(true),
+ theOrientationMatrixValidFlag(true),
+ theTargetWidthInMetersValidFlag(true),
+ theTargetWidthInMeters(0.0),
+ theSlantRangeValidFlag(true),
+ theSlantRange(0.0),
+ theReferenceTime(0.0),
+ theClock(0.0)
+ {
+ }
+ CoordinateInfo(const CoordinateInfo& src)
+ :theFrameCenterLlhValidFlag(src.theFrameCenterLlhValidFlag),
+ theFrameCenterLlh(src.theFrameCenterLlh),
+ theSensorPositionLlhValidFlag(src.theSensorPositionLlhValidFlag),
+ theSensorPositionLlh(src.theSensorPositionLlh),
+ theOrientationMatrixValidFlag(src.theOrientationMatrixValidFlag),
+ theOrientationMatrix(src.theOrientationMatrix),
+ theTargetWidthInMetersValidFlag(src.theTargetWidthInMetersValidFlag),
+ theTargetWidthInMeters(src.theTargetWidthInMeters),
+ theSlantRangeValidFlag(src.theSlantRangeValidFlag),
+ theSlantRange(src.theSlantRange),
+ theCornerPoints(src.theCornerPoints),
+ theKlvTable(src.theKlvTable.valid()?src.theKlvTable->dup():(ossimPredatorKlvTable*)0),
+ theReferenceTime(src.theReferenceTime),
+ theClock(src.theClock),
+ theDescription(src.theDescription)
+ {}
+ CoordinateInfo* dup()const
+ {
+ return new CoordinateInfo(*this);
+ }
+ void setDescriptionToKlvMetadata();
+
+ bool theFrameCenterLlhValidFlag;
+ osg::Vec3d theFrameCenterLlh;
+ bool theSensorPositionLlhValidFlag;
+ osg::Vec3d theSensorPositionLlh;
+ bool theOrientationMatrixValidFlag;
+ osg::Matrixd theOrientationMatrix;
+ bool theTargetWidthInMetersValidFlag;
+ ossim_float64 theTargetWidthInMeters;
+ bool theSlantRangeValidFlag;
+ ossim_float64 theSlantRange;
+ std::vector<osg::Vec3d> theCornerPoints;
+ ossimRefPtr<ossimPredatorKlvTable> theKlvTable;
+ double theReferenceTime;
+ double theClock;
+ ossimString theDescription; // html or text formatted description field.
+ };
+ class OSSIMPLANET_DLL Callback : public osg::Referenced
+ {
+ public:
+ // will add callbacks for when the geometry changed so we can update the drawables position
+ //
+ virtual void coordinatesChanged(ossimRefPtr<ossimPredatorKlvTable> /* originalTable */,
+ osg::ref_ptr<CoordinateInfo> /* transformedInfo*/ ){}
+
+ virtual void referenceTimeChanged(ossim_float64 /* reference */){}
+ };
+ ossimPlanetFFMpegImageStream();
+ virtual ~ossimPlanetFFMpegImageStream();
+ void setModel(osg::ref_ptr<ossimPlanetGeoRefModel> model)
+ {
+ theModel = model;
+ }
+ const osg::ref_ptr<ossimPlanetGeoRefModel> model()const
+ {
+ return theModel.get();
+ }
+ void setVideo(ossimRefPtr<ossimPredatorVideo> video);
+ virtual int cancel();
+
+ virtual void run();
+ virtual void play();
+ virtual void pause();
+ virtual void rewind();
+ virtual void quit(bool /*waitForThreadToExit*/ = true);
+ virtual double getLength() const;
+
+ virtual void setReferenceTime(double);
+ virtual double getReferenceTime();
+
+ virtual void setTimeMultiplier(double);
+ virtual double getTimeMultiplier();
+
+ virtual void setVolume(float);
+ virtual float getVolume();
+ void updateThreadBlock()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ // setting true will release the block
+ theBlock->set((theVideo.valid())&&
+ ((!theVideo->firstFrameFlag()||theVideo->seekingFlag())||
+ (theEnableFlag&&(_status == osg::ImageStream::PLAYING))));
+ }
+ void setEnableFlag(bool flag)
+ {
+ theMutex.lock();
+ theEnableFlag = flag;
+ theMutex.unlock();
+ updateThreadBlock();
+ }
+ void setCallback( osg::ref_ptr<ossimPlanetFFMpegImageStream::Callback> callback)
+ {
+ theCallback = callback;
+ }
+ void setNeedFirstFrameFlag(bool flag)
+ {
+ theMutex.lock();
+ theNeedFirstFrameFlag = flag;
+ theMutex.unlock();
+ updateThreadBlock();
+ }
+protected:
+ ossimPlanetReentrantMutex theMutex;
+ osg::ref_ptr<ossimPlanetRefBlock> theBlock;
+ ossimRefPtr<ossimPredatorVideo> theVideo;
+ ossim_float64 theFrameRate;
+ ossim_float64 theSecondsToUpdate;
+ bool theDoneFlag;
+ bool theEnableFlag;
+ bool theNeedFirstFrameFlag;
+ osg::ref_ptr<ossimPlanetFFMpegImageStream::Callback> theCallback;
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+};
+
+class OSSIMPLANET_DLL ossimPlanetPredatorVideoLayerNode : public ossimPlanetVideoLayerNode
+{
+public:
+ class ImageStreamCallback : public ossimPlanetFFMpegImageStream::Callback
+ {
+ public:
+ ImageStreamCallback(ossimPlanetPredatorVideoLayerNode* layer)
+ :theLayer(layer)
+ {}
+ virtual void coordinatesChanged(ossimRefPtr<ossimPredatorKlvTable> /* originalTable */,
+ osg::ref_ptr<ossimPlanetFFMpegImageStream::CoordinateInfo> transformedInfo)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theLayer->theCoordinateMutex);
+ theLayer->notifyPropertyChanged(theLayer, "coordinates");
+ theLayer->theCoordinates = transformedInfo->dup();
+ theLayer->setDescription(transformedInfo->theDescription);
+ }
+ virtual void referenceTimeChanged(ossim_float64 /* reference */)
+ {
+ theLayer->notifyPropertyChanged(theLayer, "referenceTime");
+ theLayer->setRedrawFlag(true);
+ }
+ protected:
+ ossimPlanetPredatorVideoLayerNode* theLayer;
+ };
+ friend class ImageStreamCallback;
+ ossimPlanetPredatorVideoLayerNode(ossimPlanetVideoLayer* layer=0);
+ virtual ~ossimPlanetPredatorVideoLayerNode();
+ virtual bool open(const ossimFilename& file);
+ virtual void setVideo(ossimPredatorVideo* video);
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ virtual void pause();
+ virtual void rewind();
+ virtual void play();
+ virtual ossim_float64 duration()const;
+ ossimPlanetVideoLayerNode::Status status()const;
+ virtual void setReferenceTime(ossim_float64 reference);
+ virtual ossim_float64 referenceTime()const;
+ virtual void setRenderMode(ossimPlanetVideoLayerNode::RenderMode mode);
+ virtual void stage()
+ {
+ setStagedFlag(true);
+ }
+ virtual void update()
+ {
+ }
+
+ virtual void setEnableFlag(bool flag)
+ {
+ if(theCurrentFrame.valid())
+ {
+ theCurrentFrame->setEnableFlag(flag);
+ }
+ ossimPlanetVideoLayerNode::setEnableFlag(flag);
+ }
+
+protected:
+ void updateIconGeometry();
+
+ ossimRefPtr<ossimPredatorVideo> theVideo;
+ ossim_float64 theFrameRate;
+ ossim_float64 theSecondsToUpdate;
+ osg::ref_ptr<ossimPlanetFFMpegImageStream> theCurrentFrame;
+ osg::Timer_t theCurrentTime;
+
+ osg::ref_ptr<osg::Switch> theSwitchNode;
+
+ ossim_float64 theAspect;
+ ossim_float64 theInvAspect;
+ bool theGeometryFlag;
+ bool theCullFlag;
+ osg::ref_ptr<ossimPlanetFFMpegImageStream::CoordinateInfo> theCoordinates;
+ ossim_float64 theCullDistance;
+ osg::Vec3d theFrameCenter;
+
+ /**
+ * This is the base drawable for all draw modes
+ */
+ osg::ref_ptr<osg::Texture2D> theSharedTexture;
+ osg::ref_ptr<ossimPlanetIconGeom> theIcon;
+ ossimPlanetReentrantMutex thePredatorTraverseMutex;
+
+
+ /**
+ * Used by the 2-D HUD mode drawing for setting the ortho matrix of the camera
+ */
+ bool theViewportChangedFlag;
+
+ osg::ref_ptr<osg::Geode> theSharedGeode;
+
+ /**
+ * Used by the 2-D display mode
+ */
+ osg::ref_ptr<osg::CameraNode> theCameraNode;
+ osg::ref_ptr<osg::Viewport> theViewport;
+ osg::ref_ptr<osg::MatrixTransform> the2DMatrixTransform;
+
+ /**
+ * Used by the Billboard display mode.
+ */
+ osg::ref_ptr<ossimPlanetBillboardIcon> theBillboard;
+ osg::ref_ptr<osg::MatrixTransform> theBillboardMatrixTransform;
+ osg::ref_ptr<ossimPlanetPredatorVideoLayerNode::ImageStreamCallback> theCallback;
+ ossimPlanetReentrantMutex theCoordinateMutex;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetPrimaryBody.h b/ossimPlanet/include/ossimPlanet/ossimPlanetPrimaryBody.h
new file mode 100644
index 0000000..1f358cc
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetPrimaryBody.h
@@ -0,0 +1,130 @@
+#ifndef ossimPlanetPrimaryBody_HEADER
+#define ossimPlanetPrimaryBody_HEADER
+#include <osg/Referenced>
+// data associated with astronomical bodies (see bottom for earth and moon values)
+
+#include <math.h>
+#include <ossimPlanet/mkUtils.h>
+#include <string>
+/* #include "eassert.h" */
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetPrimaryBody : public osg::Referenced
+{
+public:
+ ossimPlanetPrimaryBody(const std::string& name, double equatorialRadius, double polarRadius, double signedSecondsPerDay, double mass, double minLon, double maxLon) :
+ name_(name),
+ equatorialRadius_(equatorialRadius),
+ polarRadius_(polarRadius),
+ rotationSpeed_(360.0/signedSecondsPerDay),
+ secondsPerDay_(fabs(signedSecondsPerDay)),
+ mass_(mass),
+ mu_(mass*6.67259e-20), // mass * newton's universal gravitational constant in km not meters
+ minLon_(minLon),
+ maxLon_(maxLon)
+ {
+/* require(!name.empty()); */
+/* require(equatorialRadius > 0.0); */
+/* require(polarRadius > 0.0); */
+/* require(mass > 0.0); */
+/* require(minLon < maxLon); */
+
+ if (secondsPerDay_ == 0.0)
+ rotationSpeed_ = 0.0;
+ }
+
+ const std::string& name() const
+ // name of the body
+ { return name_; }
+
+ double equatorialRadius() const
+ // equatorial radius in meters (aka a)
+ { return equatorialRadius_; }
+
+ double polarRadius() const
+ // polar radius in meters (aka b)
+ { return polarRadius_; }
+
+ double meanRadius() const
+ // mean of equatorialRadius() and polarRadius()
+ { return (equatorialRadius_ + polarRadius_)/2.0; }
+
+ double radius(double latitudeDeg) const
+ // distance from center of primary to mean sea level (?) at given latitude
+ {
+ double c = cos(osg::DegreesToRadians(latitudeDeg)) / equatorialRadius_;
+ double s = sin(osg::DegreesToRadians(latitudeDeg)) / polarRadius_;
+ return sqrt(1.0/(c*c + s*s));
+ }
+
+ double rotationSpeed() const
+ // rotation speed in degrees per second, anticlockwise from north pole
+ { return rotationSpeed_; }
+
+ double secondsPerDay() const
+ // number of seconds in a day
+ { return secondsPerDay_; }
+
+ double mass() const
+ // mass in kg
+ { return mass_; }
+
+ double mu() const
+ // mass * newton universal gravitational constant in km^3/s^2
+ { return mu_; }
+
+ double minLon() const
+ // min longitude
+ { return minLon_; }
+
+ double maxLon() const
+ // max longitude
+ { return maxLon_; }
+
+
+protected:
+ std::string name_;
+ // primary name
+
+ double equatorialRadius_;
+ // equatorial radius in meters (aka a)
+
+ double polarRadius_;
+ // polar radius in meters (aka b)
+
+ double rotationSpeed_;
+ // rotation speed in degrees per second
+
+ double secondsPerDay_;
+ // number of seconds in a day
+
+ double mass_;
+ // mass in kg
+
+ double mu_;
+ // mass * newton universal gravitational constant in km^3/s^2
+
+ double minLon_;
+ // min longitude
+
+ double maxLon_;
+ // max longitude
+
+};
+
+#endif
+
+
+/*
+ # arglist values are:
+ # primary name
+ # equatorial radius in meters
+ # polar radius in meters
+ # seconds per day (negative if rotates clockwise from north pole, 0 if no rotation)
+ # mass in kg
+ # min longitude
+ # max longitude
+
+ earth_wgs84 6378137.0 6356752.3142 86400 5.9742e24 -180 180
+ moon 1737400.0 1737400.0 0 7.3483e22 0 360
+ */
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetReentrantMutex.h b/ossimPlanet/include/ossimPlanet/ossimPlanetReentrantMutex.h
new file mode 100644
index 0000000..95cc633
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetReentrantMutex.h
@@ -0,0 +1,110 @@
+#ifndef ossimPlanetReentrantMutex_HEADER
+#define ossimPlanetReentrantMutex_HEADER
+#include <OpenThreads/Thread>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+
+/**
+ * This is out of SVN for the nex 2.8.1 release of OSG. There was a bug in the lock and unlock
+ * I will use this until the new 2.8.1 comes out.
+ */
+class ossimPlanetReentrantMutex : public OpenThreads::Mutex
+{
+public:
+
+ ossimPlanetReentrantMutex():
+ _threadHoldingMutex(0),
+ _lockCount(0) {}
+
+ virtual ~ossimPlanetReentrantMutex() {}
+
+ virtual int lock()
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
+ if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
+ {
+ ++_lockCount;
+ return 0;
+ }
+ }
+
+ int result = Mutex::lock();
+ if (result==0)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
+
+ _threadHoldingMutex = OpenThreads::Thread::CurrentThread();
+ _lockCount = 1;
+ }
+ return result;
+ }
+
+
+ virtual int unlock()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
+#if 0
+ if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
+ {
+ --_lockCount;
+ if (_lockCount<=0)
+ {
+ _threadHoldingMutex = 0;
+ return Mutex::unlock();
+ }
+ }
+ else
+ {
+ osg::notify(osg::NOTICE)<<"Error: ReentrantMutex::unlock() - unlocking from the wrong thread."<<std::endl;
+ }
+#else
+ if (_lockCount>0)
+ {
+ --_lockCount;
+ if (_lockCount<=0)
+ {
+ _threadHoldingMutex = 0;
+ return Mutex::unlock();
+ }
+ }
+#endif
+ return 0;
+ }
+
+
+ virtual int trylock()
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
+ if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
+ {
+ ++_lockCount;
+ return 0;
+ }
+ }
+
+ int result = Mutex::trylock();
+ if (result==0)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
+
+ _threadHoldingMutex = OpenThreads::Thread::CurrentThread();
+ _lockCount = 1;
+ }
+ return result;
+ }
+
+private:
+
+ ossimPlanetReentrantMutex(const ossimPlanetReentrantMutex&):OpenThreads::Mutex() {}
+
+ ossimPlanetReentrantMutex& operator =(const ossimPlanetReentrantMutex&) { return *(this); }
+
+ OpenThreads::Thread* _threadHoldingMutex;
+
+ OpenThreads::Mutex _lockCountMutex;
+ unsigned int _lockCount;
+
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetRefBlock.h b/ossimPlanet/include/ossimPlanet/ossimPlanetRefBlock.h
new file mode 100644
index 0000000..4f42083
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetRefBlock.h
@@ -0,0 +1,15 @@
+#ifndef ossimPlanetRefBlock_HEADER
+#define ossimPlanetRefBlock_HEADER
+#include <osg/Referenced>
+#include <OpenThreads/Block>
+#include "ossimPlanetExport.h"
+
+class OSSIMPLANET_DLL ossimPlanetRefBlock : virtual public osg::Referenced,
+ public OpenThreads::Block
+{
+public:
+ ossimPlanetRefBlock()
+ {}
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetSceneView.h b/ossimPlanet/include/ossimPlanet/ossimPlanetSceneView.h
new file mode 100644
index 0000000..ff7728e
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetSceneView.h
@@ -0,0 +1,37 @@
+#ifndef ossimPlanetSceneView_HEADER
+#define ossimPlanetSceneView_HEADER
+#include<osgUtil/SceneView>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osgUtil/IntersectVisitor>
+
+class OSSIMPLANET_DLL ossimPlanetSceneView : public osgUtil::SceneView
+{
+public:
+ ossimPlanetSceneView();
+ virtual bool pickObjects(osgUtil::IntersectVisitor::HitList& hits,
+ osg::Node* startNode,
+ double vx, double vy,
+ double startPointShift);
+
+/* virtual bool intersectScene(osg::Node* startNode, */
+/* osg::Vec3d& intersection, */
+/* const osg::Vec3d& startPt, */
+/* const osg::Vec3d& endPt); */
+ virtual bool intersectScene(osg::Node* startNode,
+ osg::Vec3d& intersectionPoint,
+ double vx, double vy,
+ double startPointShift=0.0);
+/* virtual bool computeNadirIntersection(osg::Vec3d& intersectionPoint, */
+/* double startPointShift=0.0); */
+ virtual bool computeLineOfSiteIntersection(osg::Vec3d& intersectionPoint,
+ double startPointShift=0.0);
+ void getEyePosition(osg::Vec3d& eye)const;
+ void getLookDirection(osg::Vec3d& direction)const;
+/* bool makeRay(osg::Vec3d& origin, */
+/* osg::Vec3d& ray, */
+/* double vx, double vy); */
+
+protected:
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetServerMessageHandler.h b/ossimPlanet/include/ossimPlanet/ossimPlanetServerMessageHandler.h
new file mode 100644
index 0000000..86ea8ef
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetServerMessageHandler.h
@@ -0,0 +1,30 @@
+#ifndef ossimPlanetServerMessageHandler_HEADER
+#define ossimPlanetServerMessageHandler_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/sg_socket.h>
+
+class ossimPlanetServerMessageHandler : public osg::Referenced
+{
+public:
+ ossimPlanetServerMessageHandler()
+ :theEnableFlag(true)
+ {
+ }
+ virtual bool handleMessage(const ossimString& message,
+ osg::ref_ptr<SGIOChannel> iochannel)=0;
+ void setEnableFlag(bool flag)
+ {
+ theEnableFlag = flag;
+ }
+ bool getEnableFalg()const
+ {
+ return theEnableFlag;
+ }
+
+protected:
+ bool theEnableFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetServerThread.h b/ossimPlanet/include/ossimPlanet/ossimPlanetServerThread.h
new file mode 100644
index 0000000..e29ec37
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetServerThread.h
@@ -0,0 +1,75 @@
+#ifndef ossimPlanetServerThread_HEADER
+#define ossimPlanetServerThread_HEADER
+#include <queue>
+#include "ossimPlanetExport.h"
+#include <ossimPlanet/sg_socket.h>
+#include <ossimPlanet/ossimPlanetServerMessageHandler.h>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include <OpenThreads/Thread>
+#include<ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimString.h>
+
+
+class OSSIMPLANET_DLL ossimPlanetServerThread : public osg::Referenced,
+ public OpenThreads::Thread
+{
+public:
+ ossimPlanetServerThread(ossim_uint32 maxQueueSize = 2048);
+ virtual ~ossimPlanetServerThread();
+ virtual void run();
+ virtual int cancel();
+
+ void setQueueMessagesFlag(bool flag);
+ bool getQueueMessagesFlag()const;
+ /**
+ * Adds a port listener.
+ *
+ * @param host The host ip address. Usually will be localhost or empty string
+ * @param port The port number.
+ * @param portType The port type can be udp or tcp listener
+ */
+ osg::ref_ptr<SGSocket> addServer(const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType,
+ char delimiter='\n');
+
+ osg::ref_ptr<SGSocket> removeServer(ossim_uint32 idx);
+ osg::ref_ptr<SGSocket> removeServer(const ossimString& host,
+ const ossimString& port);
+
+ ossim_uint32 getNumberOfServers()const;
+
+ bool setServer(ossim_uint32 idx,
+ const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType);
+
+ ossimString getPort(ossim_uint32 idx)const;
+ ossimString getServer(ossim_uint32 idx)const;
+ ossimString getPortType(ossim_uint32 idx)const;
+
+ bool nextMessage(ossimString& msg);
+
+ void addMessageHandler(osg::ref_ptr<ossimPlanetServerMessageHandler> messageHandler);
+ void removeMessageHandler(osg::ref_ptr<ossimPlanetServerMessageHandler> messageHandler);
+ ossim_uint32 getNumberOfMessageHandlers()const;
+
+protected:
+ int findMessageHandler(ossimPlanetServerMessageHandler* handler)const;
+
+ mutable ossimPlanetReentrantMutex theMessageQueueMutex;
+ mutable ossimPlanetReentrantMutex theChannelListMutex;
+ mutable ossimPlanetReentrantMutex theMessageHandlerMutex;
+ ossim_uint32 thePollingRatePerSecond;
+ ossim_uint32 theMaxQueueSize;
+ std::queue<ossimString> theMessageQueue;
+ std::vector<osg::ref_ptr<SGSocket> > theChannelList;
+ bool theDoneFlag;
+ bool theStartedFlag;
+ bool theQueueMessagesFlag;
+ std::vector<osg::ref_ptr<ossimPlanetServerMessageHandler> > theMessageHandlerList;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetSetup.h b/ossimPlanet/include/ossimPlanet/ossimPlanetSetup.h
new file mode 100644
index 0000000..53bd339
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetSetup.h
@@ -0,0 +1,8 @@
+#ifndef ossimPlanetSetup_HEADER
+#define ossimPlanetSetup_HEADER
+
+// Comment this out if you want to build without ephemeris support
+// On by default
+#define OSSIMPLANET_HAS_LIBZ
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetShaderProgramSetup.h b/ossimPlanet/include/ossimPlanet/ossimPlanetShaderProgramSetup.h
new file mode 100644
index 0000000..7c8ec29
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetShaderProgramSetup.h
@@ -0,0 +1,86 @@
+#ifndef ossimPlanetShaderProgramSetup_HEADER
+#define ossimPlanetShaderProgramSetup_HEADER
+#include <osg/Referenced>
+#include <osg/Program>
+#include <osg/Shader>
+#include <osg/Uniform>
+#include <vector>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetShaderProgramSetup : public osg::Referenced
+{
+public:
+ enum ossimPlanetFragmentShaderType
+ {
+ NO_SHADER = 0,
+ TOP,
+ REFERENCE,
+ OPACITY,
+ HORIZONTAL_SWIPE,
+ VERTICAL_SWIPE,
+ BOX_SWIPE,
+ CIRCLE_SWIPE,
+ ABSOLUTE_DIFFERENCE,
+ FALSE_COLOR_REPLACEMENT
+ };
+ ossimPlanetShaderProgramSetup(ossim_uint32 minNumberOfTextureArguments=2)
+ :theMinNumberOfTextureArguments(minNumberOfTextureArguments),
+ theFragmentShaderType(NO_SHADER)
+ {
+ }
+ void setProgram(osg::Program* program)
+ {
+ theProgram = program;
+ }
+ osg::Program* getProgram()
+ {
+ return theProgram.get();
+ }
+ const osg::Program* getProgram()const
+ {
+ return theProgram.get();
+ }
+ ossim_uint32 getNumberOfUniforms()const
+ {
+ return theUniformList.size();
+ }
+ osg::ref_ptr<osg::Uniform> getUniform(const ossimString& name);
+ osg::ref_ptr<osg::Uniform> getUniform(ossim_uint32 idx)
+ {
+ if(idx < theUniformList.size())
+ {
+ return theUniformList[idx].get();
+ }
+
+ return 0;
+ }
+ void clearUniformList()
+ {
+ theUniformList.clear();
+ }
+
+ void addUniform(osg::Uniform* uniform)
+ {
+ theUniformList.push_back(uniform);
+ }
+ ossim_uint32 minNumberOfTextureArguments()const
+ {
+ return theMinNumberOfTextureArguments;
+ }
+ void setFragmentType(ossimPlanetFragmentShaderType fragType)
+ {
+ theFragmentShaderType = fragType;
+ }
+ ossimPlanetFragmentShaderType fragmentType()const
+ {
+ return theFragmentShaderType;
+ }
+protected:
+ ossim_uint32 theMinNumberOfTextureArguments;
+ osg::ref_ptr<osg::Program> theProgram;
+ std::vector<osg::ref_ptr<osg::Uniform> > theUniformList;
+ ossimPlanetFragmentShaderType theFragmentShaderType;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetSocketNetworkConnection.h b/ossimPlanet/include/ossimPlanet/ossimPlanetSocketNetworkConnection.h
new file mode 100644
index 0000000..2f2eefd
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetSocketNetworkConnection.h
@@ -0,0 +1,68 @@
+class ossimPlanetSocketNetworkConnection;
+#ifndef ossimPlanetSocketNetworkConnection_H
+#define ossimPlanetSocketNetworkConnection_H
+
+#include <ossimPlanet/sg_socket.h>
+#include <ossimPlanet/netBuffer.h>
+#include <osg/ref_ptr>
+// point to point socket connection.
+// XXX see bugs below
+
+#include <string>
+/* #include <sys/time.h> */
+#include "ossimPlanet/ossimPlanetNetworkConnection.h"
+
+class ossimPlanetSocketNetworkConnection : public ossimPlanetNetworkConnection
+{
+public:
+ class ossimPlanetNetSocketRef : public netSocket,
+ public osg::Referenced
+ {
+ public:
+ ossimPlanetNetSocketRef(){}
+ virtual ~ossimPlanetNetSocketRef(){}
+ };
+ ossimPlanetSocketNetworkConnection(const std::string& hostname, int port, char delimiter = '\0');
+ ~ossimPlanetSocketNetworkConnection();
+
+ void send(const ossimPlanetAction& a, const std::string& destination);
+ // XXX doesn't really handle destination correctly
+ // we don't encode the destination (or the origin) of the sent Action.
+ // so the remote receiver has to infer origin from which socket he got it off of.
+ // also the remote receiver can't know the intended destination, since we don't
+ // encode it and broadcast it to all NetworkConnections.
+
+ void receive();
+ // XXX doesn't yet handle broadcast semantics or destination correctly.
+ // XXX our protocol here doesn't support origin names, so we just use
+ // the NetworkConnection name as the originating federate name.
+
+protected:
+ void attemptToFlushOutBuffer();
+ // if outBuffer_ is not empty, write() as much of it as possible and remove the written part from outBuffer_
+ // assert(socket_ >= 0)
+
+// osg::ref_ptr<SGSocket> theSocket;
+ osg::ref_ptr<ossimPlanetNetSocketRef> theSocket;
+ char actionDelimiter_;
+ // character that marks end of action. usually \n or \0
+
+ std::string inBuffer_;
+ // buffer for accumulating incoming Actions
+
+ std::string outBuffer_;
+ // buffer for accumulating outgoing Actions, in the case of write() failing somehow.
+
+
+#if 0
+ int socket_;
+ // socket descriptor
+
+ struct timeval timeout_;
+ // select() timeout structure
+
+#endif
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetSousaLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetSousaLayer.h
new file mode 100644
index 0000000..a2bf2c9
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetSousaLayer.h
@@ -0,0 +1,97 @@
+#ifndef ossimPlanetSousaLayer_HEADER
+#define ossimPlanetSousaLayer_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <ossimPlanet/ossimPlanetAnnotationLayer.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <OpenThreads/Mutex>
+#include <map>
+#include <ossimPlanet/ossimPlanetArchive.h>
+
+
+class ossimPlanet;
+class ossimPlanetKmlLayer;
+class OSSIMPLANET_DLL ossimPlanetSousaLayer : public ossimPlanetLayer
+{
+public:
+ ossimPlanetSousaLayer();
+ virtual ~ossimPlanetSousaLayer();
+
+ /**
+ * For now this will remove any current connection and then replace with the passed in
+ * connection. All previous entities are cleared from the scene graph.
+ */
+ void setConnection(const ossimString& name,
+ const ossimString& ip,
+ const ossimString& port,
+ const ossimString& portType);
+
+ /**
+ * add <object definition>
+ *
+ * for annotation adds see the ossimPlanetAnnotationLayer execute.
+ *
+ */
+ virtual void execute(const ossimPlanetAction &a);
+ void closeConnections();
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ // added by russc 5/5/08
+ void setArchive(osg::ref_ptr<ossimPlanetArchive> archive);
+
+ void setIdentity(const ossimString& tempUserName,
+ const ossimString& tempDomain);
+ const ossimString& username()const;
+ const ossimString& domain()const;
+
+protected:
+ class ossimPlanetSousaXmlActionOperation;
+ friend class ossimPlanetSousaXmlActionOperation;
+ virtual void xmlExecute(const ossimPlanetXmlAction &a);
+ virtual void threadedXmlExecute(const ossimPlanetXmlAction &a);
+ void removeImage(const ossimString& name,
+ const ossimString& id);
+ void removeAnnotation(const ossimString& name,
+ const ossimString& id);
+ void addImageLayer(const ossimXmlNode* imageObject);
+ void addImageToGroup(ossimPlanetTextureLayerGroup* group, const ossimXmlNode* imageObject);
+ void setClientSocket(const ossimXmlNode* node);
+ void sendViewMessage();
+ void sendIdentityMessage();
+
+ ossimString theConnectionName;
+ ossimString theConnectionIp;
+ ossimString theConnectionPort;
+ ossimString theConnectionPortType;
+ ossimString theIoThreadReceiverName;
+
+ ossimString theUserName;
+ ossimString theDomain;
+
+ bool theZuiInitializedFlag;
+ bool theViewChangedFlag;
+ double theViewMessageRate;
+ osg::Timer_t theViewChangeStart;
+ osg::Vec3d theEyePosition;
+ osg::Vec3d theEyeOrientation;
+
+
+ osg::ref_ptr<ossimPlanetAnnotationLayer> theAnnotationLayer;
+ osg::ref_ptr<ossimPlanetArchive> theArchive;
+
+ ossimPlanetReentrantMutex theCameraTestDelayMutex;
+ ossim_int32 theCameraTestDelay;
+ mutable ossimPlanetReentrantMutex theUpdateMutex;
+
+ mutable ossimPlanetReentrantMutex theXmlActionThreadQueueMutex;
+
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> theXmlActionThreadQueue;
+
+ osg::ref_ptr<ossimPlanetNodeReraiseCallback> theNodeCallback;
+
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> theSousaImageGroup;
+ bool theNeedToAddImageGroupFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetSrtmElevationDatabase.h b/ossimPlanet/include/ossimPlanet/ossimPlanetSrtmElevationDatabase.h
new file mode 100644
index 0000000..1448e90
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetSrtmElevationDatabase.h
@@ -0,0 +1,65 @@
+#ifndef ossimPlanetSrtmElevationDatabase_HEADER
+#define ossimPlanetSrtmElevationDatabase_HEADER
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <osg/Timer>
+#include <ossim/imaging/ossimImageRenderer.h>
+#include <ossim/imaging/ossimOrthoImageMosaic.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/elevation/ossimSrtmHandler.h>
+class OSSIMPLANET_DLL ossimPlanetSrtmElevationDatabase : public ossimPlanetElevationDatabase
+{
+public:
+ ossimPlanetSrtmElevationDatabase();
+ ossimPlanetSrtmElevationDatabase(const ossimPlanetSrtmElevationDatabase& src);
+ virtual ~ossimPlanetSrtmElevationDatabase();
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ virtual void resetStats()const;
+ virtual ossimPlanetTextureLayerStateCode open(const std::string& location);
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+
+protected:
+ class SrtmInfo : public osg::Referenced
+ {
+ public:
+ double theMinLat, theMinLon, theMaxLat, theMaxLon;
+ std::string theFilename;
+ ossimRefPtr<ossimSrtmHandler> theSrtmHandler;
+ osg::Timer_t theTimeStamp;
+ };
+ typedef std::map<std::string, osg::ref_ptr<SrtmInfo> > SrtmFilePointerList;
+
+
+ osg::ref_ptr<ossimPlanetSrtmElevationDatabase::SrtmInfo> getInfo(const std::string& srtmName);
+ void shrinkFilePointers();
+ ossimFilename buildFilename(double lat, double lon)const;
+ osg::ref_ptr<ossimPlanetSrtmElevationDatabase::SrtmInfo> findSrtmInfo(const std::string& srtmName);
+
+ std::string theLocation;
+ mutable bool theOpenFlag;
+ ossim_uint32 theMaxOpenFiles;
+ ossim_uint32 theMinOpenFiles;
+ SrtmFilePointerList theFilePointers;
+/* ossimRefPtr<ossimMapProjection> theProjection; */
+/* ossimRefPtr<ossimImageRenderer> theRenderer; */
+/* ossimRefPtr<ossimOrthoImageMosaic> theMosaic; */
+/* ossim_float32 theNullHeightValue; */
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetStandardTextureLayerFactory.h b/ossimPlanet/include/ossimPlanet/ossimPlanetStandardTextureLayerFactory.h
new file mode 100644
index 0000000..e651de9
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetStandardTextureLayerFactory.h
@@ -0,0 +1,30 @@
+#ifndef ossimPlanetStandardTextureLayerFactory_HEADER
+#define ossimPlanetStandardTextureLayerFactory_HEADER
+#include <OpenThreads/Mutex>
+#include <ossimPlanet/ossimPlanetTextureLayerFactory.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetStandardTextureLayerFactory : public ossimPlanetTextureLayerFactory
+{
+public:
+ ossimPlanetStandardTextureLayerFactory();
+
+ static ossimPlanetStandardTextureLayerFactory* instance();
+ virtual osg::ref_ptr<ossimPlanetTextureLayer> createLayer(const ossimString& name, bool openAllEntriesFlag)const;
+
+protected:
+ ossimPlanetStandardTextureLayerFactory(const ossimPlanetStandardTextureLayerFactory& src):ossimPlanetTextureLayerFactory(src) { }
+ const ossimPlanetStandardTextureLayerFactory& operator =(const ossimPlanetStandardTextureLayerFactory& ) { return *this;}
+
+ osg::ref_ptr<ossimPlanetTextureLayer> createLayerFromFilename(const ossimFilename& name, bool openAllEntriesFlag)const;
+ osg::ref_ptr<ossimPlanetTextureLayer> createLayerFromKwl(const ossimKeywordlist& kwl,
+ const ossimString& prefix=ossimString())const;
+ osg::ref_ptr<ossimPlanetTextureLayer> createLayerFromOldKwl(const ossimKeywordlist& kwl,
+ const ossimString& prefix=ossimString())const;
+ static ossimPlanetStandardTextureLayerFactory* theInstance;
+ mutable ossimPlanetReentrantMutex theMutex;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTerrain.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrain.h
new file mode 100644
index 0000000..821711c
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrain.h
@@ -0,0 +1,435 @@
+#ifndef ossimPlanetTerrain_HEADER
+#define ossimPlanetTerrain_HEADER
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <ossimPlanet/ossimPlanetTerrainTile.h>
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetElevationDatabaseGroup.h>
+#include <osg/TexMat>
+#include <osg/Timer>
+#include <osg/GraphicsContext>
+#include <osg/Geometry>
+#include <osg/BufferObject>
+#include <osgDB/DatabasePager>
+#include <osgUtil/UpdateVisitor>
+#include <osgUtil/CullVisitor>
+#include <ossimPlanet/ossimPlanetElevationDatabaseGroup.h>
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetTileRequest.h>
+#include <ossimPlanet/ossimPlanetCache.h>
+#include <set>
+#include <map>
+#include <queue>
+
+/**
+ *
+ */
+class OSSIMPLANET_DLL ossimPlanetTerrain : public ossimPlanetLayer
+{
+public:
+ class TextureCallback;
+ class OSSIMPLANET_DLL UpdateTileCallback : public osg::NodeCallback
+ {
+ public:
+ UpdateTileCallback(ossimPlanetTerrain* terrain)
+ :theTerrain(terrain){}
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
+ virtual void update(ossimPlanetTerrainTile* tile, osg::NodeVisitor* nv);
+ protected:
+ ossimPlanetTerrain* theTerrain;
+ };
+ class OSSIMPLANET_DLL CullTileCallback : public osg::NodeCallback
+ {
+ public:
+ CullTileCallback(ossimPlanetTerrain* terrain)
+ :theTerrain(terrain){}
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
+ virtual void cull(ossimPlanetTerrainTile* tile, osg::NodeVisitor* nv);
+ protected:
+ ossimPlanetTerrain* theTerrain;
+ };
+
+ enum CullAmountType
+ {
+ NO_CULL = 0,
+ LOW_CULL,
+ MEDIUM_LOW_CULL,
+ MEDIUM_CULL,
+ MEDIUM_HIGH_CULL,
+ HIGH_CULL
+ };
+ enum TextureDensityType
+ {
+ LOW_TEXTURE_DENSITY = 0,
+ MEDIUM_LOW_TEXTURE_DENSITY,
+ MEDIUM_TEXTURE_DENSITY,
+ MEDIUM_HIGH_TEXTURE_DENSITY,
+ HIGH_TEXTURE_DENSITY
+ };
+ enum ElevationDensityType
+ {
+ LOW_ELEVATION_DENSITY = 0,
+ MEDIUM_LOW_ELEVATION_DENSITY,
+ MEDIUM_ELEVATION_DENSITY,
+ MEDIUM_HIGH_ELEVATION_DENSITY,
+ HIGH_ELEVATION_DENSITY
+ };
+ enum SplitMergeSpeedType
+ {
+ LOW_SPEED = 0,
+ MEDIUM_LOW_SPEED,
+ MEDIUM_SPEED,
+ MEDIUM_HIGH_SPEED,
+ HIGH_SPEED
+ };
+ enum SplitMergeMetricType
+ {
+ DISTANCE_METRIC = 0,
+ PIXEL_METRIC
+ };
+ class FindCompileableGLObjectsVisitor;
+ friend class UpdateTileCallback;
+ friend class CullTileCallback;
+ friend class TextureCallback;
+
+ typedef std::list<osg::ref_ptr<ossimPlanetExtents> > RefreshImageExtentsList;
+ typedef std::list<osg::ref_ptr<ossimPlanetExtents> > RefreshElevationExtentsList;
+ typedef std::list<osg::ref_ptr<ossimPlanetTerrainTile> > RemoveChildrenList;
+ typedef std::vector<osg::ref_ptr<ossimPlanetTextureLayer> > TextureLayers;
+ typedef std::map<ossimPlanetTerrainTileId, ossimPlanetTerrainTile* > TileSetMap;
+ typedef std::set<ossimPlanetTerrainTile*> TileSet;
+
+
+ ossimPlanetTerrain();
+ ossimPlanetTerrain(ossimPlanetGrid* grid);
+ virtual ~ossimPlanetTerrain();
+ void setDatabasePager(osgDB::DatabasePager* pager);
+ osgDB::DatabasePager* getDatabasePager(){return thePager.get();}
+ void setTerrainTechnique(ossimPlanetTerrainTechnique* technique);
+ ossimPlanetTerrainTechnique* newTechnique();
+
+ void setGrid(ossimPlanetGrid* grid);
+ const ossimPlanetGrid* grid()const;
+ ossimPlanetGrid* grid();
+ void removeTerrainTileFromGraph(ossimPlanetTerrainTile* tile);
+ void removeTerrainChildren(ossimPlanetTerrainTile* tile);
+
+ void requestSplit(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ ossimPlanetOperation* request);
+ void requestMerge(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ ossimPlanetOperation* request);
+ void requestTexture(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ const std::vector<ossim_uint32>& indices,
+ ossimPlanetOperation* request);
+ void requestElevation(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ ossimPlanetOperation* request);
+ void compileGLObjects(osg::State& state, double compileTime);
+
+ // Helper functions for determining if objects need to be
+ // compiled.
+ inline static bool isCompiled(const osg::Texture* texture,
+ unsigned int contextID)
+ {
+ return( texture->getTextureObject(contextID) != NULL );
+ }
+ inline static bool isCompiled(const osg::StateSet* stateSet,
+ unsigned int contextID)
+ {
+ for (unsigned i = 0;
+ i < stateSet->getTextureAttributeList().size();
+ ++i)
+ {
+ const osg::Texture* texture
+ = dynamic_cast<const osg::Texture*>(stateSet->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
+ if (texture && !isCompiled(texture, contextID))
+ return false;
+ }
+ return true;
+ }
+ inline static bool isCompiled(const osg::Drawable* drawable,
+ unsigned int contextID)
+ {
+ // Worry about vbos later
+ if (drawable->getUseDisplayList())
+ {
+ return drawable->getDisplayList(contextID) != 0;
+ }
+ else if(drawable->getUseVertexBufferObjects())
+ {
+ const osg::Geometry* geometry = drawable->asGeometry();
+ if(geometry)
+ {
+ osg::Geometry::ArrayList arrayList;
+ geometry->getArrayList(arrayList);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < arrayList.size();++idx)
+ {
+ if(arrayList[idx]->getVertexBufferObject())
+ {
+// if(arrayList[idx]->getVertexBufferObject()->isDirty(contextID))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+ bool addElevation(const ossimFilename& file, bool sortFlag=false);
+ bool addElevation(osg::ref_ptr<ossimPlanetElevationDatabase> database, bool sortFlag=false);
+
+ /**
+ * Will do a non destructive expand or shrink
+ */
+ void setNumberOfTextureLayers(ossim_uint32 size);
+
+ ossim_uint32 numberOfTextureLayers()const;
+ ossimPlanetTextureLayer* textureLayer(ossim_uint32 idx);
+ bool setTextureLayer(ossim_uint32 idx, ossimPlanetTextureLayer* layer);
+
+ ossimPlanetElevationDatabaseGroup* elevationLayer();
+ const ossimPlanetElevationDatabaseGroup* elevationLayer()const;
+
+ virtual void traverse(osg::NodeVisitor &nv);
+ static ossimPlanetTerrain* findTerrain(osg::NodePath& currentNodePath);
+
+ double maxTimeToSplit()const;
+ double maxTimeToMerge()const;
+
+ void registerTile(ossimPlanetTerrainTile* tile);
+ void unregisterTile(ossimPlanetTerrainTile* tile);
+ ossimPlanetTerrainTile* findTile(const ossimPlanetTerrainTileId& id);
+ const ossimPlanetTerrainTile* findTile(const ossimPlanetTerrainTileId& id)const;
+
+ void refreshImageLayers(ossimPlanetExtents* extents = 0);
+ void refreshElevationLayers(ossimPlanetExtents* extents = 0);
+ void refreshImageAndElevationLayers(ossimPlanetExtents* extents = 0);
+
+ void resetImageLayers();
+ void resetGraph();
+ virtual void setModel(ossimPlanetGeoRefModel* model);
+ void addRequestToReadyToApplyQueue(ossimPlanetTileRequest* request);
+ void addRequestToNeedToCompileQueue(ossimPlanetTileRequest* request);
+
+ void setMaxNumberOfOperationsToApplyToGraphPerFrame(ossim_uint32 value);
+
+ /**
+ * @brief set the cull amount used for the terrain.
+ */
+ virtual void setCullAmountType(CullAmountType cullAmount);
+ virtual void setTextureTileSize(ossim_uint32 width,
+ ossim_uint32 height);
+ ossim_uint32 textureTileWidth()const;
+ ossim_uint32 textureTileHeight()const;
+
+ virtual void setElevationTileSize(ossim_uint32 width,
+ ossim_uint32 height);
+ ossim_uint32 elevationTileWidth()const;
+ ossim_uint32 elevationTileHeight()const;
+
+ virtual void setElevationDensityType(ElevationDensityType type);
+ virtual void setTextureDensityType(TextureDensityType type);
+
+ ElevationDensityType elevationDensityType()const;
+ TextureDensityType textureDensityType()const;
+
+ void setSplitMergeMetricType(SplitMergeMetricType type);
+ SplitMergeMetricType splitMergeMetricType()const;
+ /**
+ * Split merge speed determines how fast or basically how soon the patch should split.
+ * Currently our algorithm is based solely on distance which means if you set the split
+ * merge speed type to a LOW_SPEED setting you have to move your eye closer to a patch
+ * before it is further refined. If you set the speed to a higher speed that low it
+ * progressively refines the graph sooner. So the eye can be further away and still refine without
+ * having to be close so the higher the speed the more detail you see from further away.
+ */
+ virtual void setSplitMergeSpeedType(SplitMergeSpeedType type);
+
+ /**
+ * The metric is based on a scale multiplier of the pixel dimensions of the texture.
+ * If the patch is smaller in projective scale than the mergeMetric*patchRadiusInPixels then it will
+ * merge the graph. If its larger than the splitMetric*patchRadiusInpixels then split.
+ */
+ virtual void setSplitMergePixelMetricParameters(ossim_float64 mergeMetric,
+ ossim_float64 splitMetric);
+ ossim_float64 splitPixelMetric()const;
+ ossim_float64 mergePixelMetric()const;
+
+ virtual void setSplitMergeLodScale(ossim_float64 ratio);
+ ossim_float64 splitMergeLodScale()const;
+ virtual void setElevationExaggeration(ossim_float64 exaggeration);
+ ossim_float64 elevationExaggeration()const;
+ void setMinimumTimeToCompilePerFrameInSeconds(double timeInSeconds);
+ ossim_float64 minimumTimeToCompilePerFrame()const;
+ void setPrecompileEnabledFlag(bool flag);
+ bool precompileEnabledFlag()const;
+ void setElevationEnabledFlag(bool flag);
+ bool elevationEnabledFlag()const;
+ void initElevation();
+
+ void setElevationMemoryCache(ossimPlanetMemoryImageCache* cache)
+ {
+ thePropertyMutex.lock();
+ theElevationCache = cache;
+ thePropertyMutex.unlock();
+ }
+ ossimPlanetImageCache* elevationCache()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theElevationCache.get();
+ }
+ const ossimPlanetImageCache* elevationCache()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theElevationCache.get();
+ }
+
+ bool priorityPointFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return thePriorityPointFlag;
+ }
+ void setPriorityPointFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ thePriorityPointFlag = flag;
+ }
+ void setPriorityPointXyz(const osg::Vec3d& pt)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ thePriorityPoint = pt;
+ }
+ const osg::Vec3d& priorityPoint()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return thePriorityPoint;
+ }
+
+
+ bool falseEyeFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFalseEyeFlag;
+ }
+ void setFalseEyeFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFalseEyeFlag = flag;
+ }
+ void setFalseEyeXyz(const osg::Vec3d& eye)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFalseEye = eye;
+ }
+ const osg::Vec3d& falseEye()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFalseEye;
+ }
+
+protected:
+ void buildRoot();
+ bool resetRootsFlag()const;
+ void applyRequestsToGraph(double maxTime);
+ void compileRequests(double maxTime);
+ void pruneNeedToCompileAndAddToGraphThreadQueues();
+ void removeTerrainChildren(double maxTime = 2.0);
+ void refreshExtents();
+ osg::ref_ptr<ossimPlanetTerrainTechnique> theTerrainTechnique;
+ ossim_int64 theLastApplyToGraphFrameNumber;
+ ossim_uint32 theMaxNumberOfOperationsToApplyToGraphPerFrame;
+ mutable OpenThreads::Mutex thePropertyMutex;
+ mutable OpenThreads::ReentrantMutex theRootLayersMutex;
+ mutable OpenThreads::ReentrantMutex theTextureQueueMutex;
+ mutable OpenThreads::ReentrantMutex theElevationQueueMutex;
+ mutable OpenThreads::ReentrantMutex theSplitQueueMutex;
+ mutable OpenThreads::ReentrantMutex theMergeQueueMutex;
+
+ mutable OpenThreads::ReentrantMutex theChildrenToRemoveMutex;
+ RemoveChildrenList theChildrenToRemove;
+
+ bool theResetRootsFlag;
+ osg::ref_ptr<ossimPlanetGrid> theGrid;
+
+ std::vector<osg::ref_ptr<ossimPlanetTerrainTile> > theRootLayers;
+
+ TextureLayers theTextureLayers;
+ osg::ref_ptr<ossimPlanetElevationDatabaseGroup> theElevationLayer;
+
+
+ osg::ref_ptr<ossimPlanetTileRequestThreadQueue> theElevationQueue;
+ osg::ref_ptr<ossimPlanetTileRequestThreadQueue> theTextureQueue;
+
+
+ /**
+ *
+ */
+ osg::ref_ptr<ossimPlanetTileRequestThreadQueue> theSplitQueue;
+ osg::ref_ptr<ossimPlanetTileRequestQueue> theMergeQueue;
+
+ OpenThreads::ReentrantMutex theReadyToApplyToGraphQueueMutex;
+ ossimPlanetTileRequest::List theReadyToApplyToGraphQueue;
+ ossimPlanetTileRequest::List theReadyToApplyToGraphNewNodesQueue;
+ OpenThreads::ReentrantMutex theNeedToCompileQueueMutex;
+ ossimPlanetTileRequest::List theNeedToCompileQueue;
+
+ double theMaxTimeToSplit;
+ double theMaxTimeToMerge;
+ mutable OpenThreads::ReentrantMutex theTileSetMutex;
+ mutable OpenThreads::ReentrantMutex theTileSetMapMutex;
+ TileSet theTileSet;
+ TileSetMap theTileSetMap;
+
+ osg::Vec3d theLastEyePosition;
+
+ osg::ref_ptr<TextureCallback> theTextureCallback;
+
+ ossim_int64 theLastFrameNumber;
+
+ osg::ref_ptr<ossimPlanetMemoryImageCache> theElevationCache;
+ osg::ref_ptr<ossimPlanetImageCacheShrinkOperation> theElevationCacheShrinkOperation;
+ osg::ref_ptr<ossimPlanetOperationThreadQueue> theCacheShrinkThreadQueue;
+
+ mutable OpenThreads::ReentrantMutex theRefreshExtentsMutex;
+ osg::ref_ptr<ossimPlanetExtents> theRefreshImageExtent;
+ osg::ref_ptr<ossimPlanetExtents> theRefreshElevationExtent;
+// RefreshImageExtentsList theRefreshImageExtentsList;
+// RefreshElevationExtentsList theRefreshElevationExtentsList;
+
+ /************************** Scene Parameters ****************/
+ osg::CullSettings::CullingModeValues theCullSettings;
+ SplitMergeMetricType theSplitMergeMetricType;
+ ossim_uint32 theTextureTileWidth;
+ ossim_uint32 theTextureTileHeight;
+ ossim_uint32 theElevationTileWidth;
+ ossim_uint32 theElevationTileHeight;
+ ossim_float64 theSplitMergeLodScale;
+ ossim_float64 theSplitPixelMetric;
+ ossim_float64 theMergePixelMetric;
+ ossim_float64 theElevationExaggeration;
+ double theMinimumTimeToCompilePerFrame;
+ bool thePrecompileEnabledFlag;
+ bool theElevationEnabledFlag;
+
+ bool theFalseEyeFlag;
+ osg::Vec3d theFalseEye;
+ bool thePriorityPointFlag;
+ osg::Vec3d thePriorityPoint;
+
+ osg::ref_ptr<osgDB::DatabasePager> thePager;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainGeometryTechnique.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainGeometryTechnique.h
new file mode 100644
index 0000000..03b4bed
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainGeometryTechnique.h
@@ -0,0 +1,255 @@
+#ifndef ossimPlanetTerrainGeometryTechnique_HEADER
+#define ossimPlanetTerrainGeometryTechnique_HEADER
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <osg/MatrixTransform>
+#include <osgUtil/CullVisitor>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/ClusterCullingCallback>
+#include <ossimPlanet/ossimPlanetBoundingBox.h>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+
+class ossimPlanetTerrainTile;
+class ossimPlanetTexture2D;
+class OSSIMPLANET_DLL ossimPlanetTerrainGeometryTechnique : public ossimPlanetTerrainTechnique
+{
+public:
+ META_Object(ossimPlanet, ossimPlanetTerrainGeometryTechnique);
+
+ class UpdateChildTextureVisitor : public osg::NodeVisitor
+ {
+ public:
+ UpdateChildTextureVisitor(ossimPlanetTexture2D* texture,
+ ossim_uint32 idx)
+ : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ theTexture(texture),
+ theIdx(idx)
+ {
+ }
+ virtual void apply(osg::Node& node);
+ protected:
+ osg::ref_ptr<ossimPlanetTexture2D> theTexture;
+ ossim_uint32 theIdx;
+ };
+ /**
+ * Local space cull node
+ */
+ class OSSIMPLANET_DLL CullNode : public osg::MatrixTransform
+ {
+ public:
+ CullNode(const ossimPlanetTerrainTileId& tileId):
+ osg::MatrixTransform(),
+ theTileId(tileId),
+ theCulledFlag(false),
+ theWithinFrustumFlag(true),
+ theEyeDistance(0.0),
+ theEyeToVolumeDistance(0.0),
+ thePixelSize(0.0)
+ {
+ setCullingActive(false);
+ }
+ CullNode(const ossimPlanetTerrainTileId& tileId,
+ osg::ref_ptr<ossimPlanetBoundingBox> boundingBox,
+ const osg::Vec3d& clusterCullingControlPoint,
+ const osg::Vec3d& clusterCullingNormal,
+ double clusterCullingDeviation,
+ double clusterCullingRadius):
+ osg::MatrixTransform(),
+ theTileId(tileId),
+ theCulledFlag(false),
+ theWithinFrustumFlag(true),
+ theBoundingBox(boundingBox),
+ theClusterCullingControlPoint(clusterCullingControlPoint),
+ theClusterCullingNormal(clusterCullingNormal),
+ theClusterCullingDeviation(clusterCullingDeviation),
+ theClusterCullingRadius(clusterCullingRadius),
+ theEyeDistance(0.0),
+ theEyeToVolumeDistance(0.0),
+ thePixelSize(0.0)
+ {
+ setCullingActive(false);
+ }
+ CullNode(const CullNode& src, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
+ :osg::MatrixTransform(src, copyop),
+ theTileId(src.theTileId),
+ theCulledFlag(src.theCulledFlag),
+ theWithinFrustumFlag(src.theWithinFrustumFlag),
+ theBoundingBox(new ossimPlanetBoundingBox(*src.theBoundingBox)),
+ theClusterCullingControlPoint(src.theClusterCullingControlPoint),
+ theClusterCullingNormal(src.theClusterCullingNormal),
+ theClusterCullingDeviation(src.theClusterCullingDeviation),
+ theClusterCullingRadius(src.theClusterCullingRadius),
+ theEyeDistance(0.0),
+ theEyeToVolumeDistance(0.0),
+ thePixelSize(0.0)
+ {
+ setCullingActive(false);
+ }
+ const ossimPlanetTerrainTileId& tileId()const
+ {
+ return theTileId;
+ }
+ void setTileId(const ossimPlanetTerrainTileId& id)
+ {
+ theTileId = id;
+ }
+ void setBoundingBox(osg::ref_ptr<ossimPlanetBoundingBox> box)
+ {
+ theBoundingBox = box.get();
+ }
+
+ const ossimPlanetBoundingBox* boundingBox()const
+ {
+ return theBoundingBox.get();
+ }
+ double eyeDistance()const
+ {
+ return theEyeDistance;
+ }
+ double eyeToVolumeDistance()const
+ {
+ return theEyeToVolumeDistance;
+ }
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ void setCulledFlag(bool flag)
+ {
+ theCulledFlag = flag;
+ }
+ bool isCulled()const
+ {
+ return theCulledFlag;
+ }
+ virtual osg::BoundingSphere computeBound() const;
+
+ double pixelSize()const
+ {
+ return thePixelSize;
+ }
+ bool withinFrustumFlag()const
+ {
+ return theWithinFrustumFlag;
+ }
+ protected:
+ ossimPlanetTerrainTileId theTileId;
+ bool theCulledFlag;
+ bool theWithinFrustumFlag;
+ osg::ref_ptr<ossimPlanetBoundingBox> theBoundingBox;
+ osg::Vec3d theClusterCullingControlPoint;
+ osg::Vec3d theClusterCullingNormal;
+ double theClusterCullingDeviation;
+ double theClusterCullingRadius;
+ double theEyeDistance;
+ double theEyeToVolumeDistance;
+ double thePixelSize;
+ };
+ friend class CullCallback;
+ ossimPlanetTerrainGeometryTechnique();
+ ossimPlanetTerrainGeometryTechnique(const ossimPlanetTerrainGeometryTechnique& src,
+ const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+ virtual ~ossimPlanetTerrainGeometryTechnique();
+ virtual void setTerrainTile(ossimPlanetTerrainTile* tile);
+ virtual void update(osgUtil::UpdateVisitor* nv);
+
+ virtual void cull(osgUtil::CullVisitor* nv);
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ virtual void buildMesh(ossimPlanetTerrainTile* optionalParent=0);
+
+ virtual void applyColorLayers(ossimPlanetTerrainTile* optionalParent=0);
+
+ virtual void applyTransparency(ossimPlanetTerrainTile* optionalParent=0);
+
+ virtual void smoothGeometry();
+ virtual void init(ossimPlanetTerrainTile* optionalParent=0);
+ //void split(bool recurse, double availableTime=2.5);
+
+ virtual void childAdded(ossim_uint32 pos);
+
+ virtual void merge();
+ virtual void removeCulledChildren();
+ bool hasCulledChildren()const;
+ bool isChildCulled(ossim_uint32 childIdx)const;
+
+ virtual double elevationPriority()const;
+ virtual double texturePriority()const;
+ virtual double mergePriority()const;
+ virtual double splitPriority()const;
+ virtual osg::BoundingSphere computeBound() const;
+
+ virtual void updateElevationMesh();
+
+ virtual ossimPlanetTexture2D* newImageLayerTexture(ossim_uint32 imageLayerIdx);
+ virtual void setChildCullParameters(ossimPlanetTerrainTile* child,
+ osg::ref_ptr<CullNode> cullNode);
+ virtual void compileGlObjects(osg::State* state);
+ virtual void setImageLayerTexture(ossimPlanetTexture2D* texture,
+ ossim_uint32 imageLayerIdx);
+ virtual void setElevationMeshFrom(ossimPlanetTerrainTile* tile);
+ virtual void vacantChildIds(TileIdList& ids)const;
+
+
+ // setup parameters
+ //
+
+
+ virtual void releaseGLObjects(osg::State* state=0);
+
+protected:
+ struct BufferData
+ {
+ osg::ref_ptr<osg::MatrixTransform> theTransform;
+ osg::ref_ptr<osg::Geode> theGeode;
+ osg::ref_ptr<osg::Geometry> theGeometry;
+ osg::Vec3d theCenterPatch;
+ osg::ref_ptr<osg::ClusterCullingCallback> theClusterCullingCallback;
+ osg::ref_ptr<CullNode> theCullNode;
+ };
+ enum ChildLocation
+ {
+ BOTTOM_LEFT = 0,
+ BOTTOM_RIGHT = 1,
+ TOP_LEFT = 2,
+ TOP_RIGHT = 3
+ };
+ enum SkirtFlags
+ {
+ NO_SKIRT = 0,
+ BOTTOM_SKIRT = 1,
+ RIGHT_SKIRT = 2,
+ TOP_SKIRT = 4,
+ LEFT_SKIRT = 8
+ };
+ ossimPlanetTexture2D* findNearestActiveParentTexture(ossim_uint32 idx, ossimPlanetTerrainTile* optionalParent=0);
+ void swapBuffers();
+ inline BufferData& readOnlyBuffer() { return theBufferData;}//theBufferData[theCurrentReadOnlyBuffer]; }
+ inline const BufferData& readOnlyBuffer()const { return theBufferData;}//[theCurrentReadOnlyBuffer]; }
+ inline BufferData& writeBuffer() { return theBufferData;}//theBufferData[theCurrentWriteBuffer]; }
+ void updateTextureMatrix(osg::StateSet* stateset,
+ ossim_uint32 imageLayerIdx,
+ const ossimPlanetTerrainTileId& startId,
+ const ossimPlanetTerrainTileId& endId);
+ bool isCulled(BufferData& buffer, osgUtil::CullVisitor* cv)const;
+ void updateChildCullSettings(osgUtil::CullVisitor* cv);
+ void markOnlyNeededChildImageLayersDirty();
+ ossim_uint32 computeSkirtFlags(const ossimPlanetTerrainTileId& childId)const;
+ void updateRequests(osg::NodeVisitor& nv);
+
+// unsigned int theCurrentReadOnlyBuffer;
+// unsigned int theCurrentWriteBuffer;
+ BufferData theBufferData;
+ ossimPlanetReentrantMutex theUpdateMutex;
+
+ ossimPlanetReentrantMutex theChildNodeCullParametersMutex;
+ std::vector<osg::ref_ptr<CullNode> > theChildNodeCullParameters;
+
+ OpenThreads::Mutex theInitMutex;
+
+ osg::Vec3d theAdjustedEye;
+ osg::Vec3d thePriorityPoint;
+ osg::BoundingSphere thePatchBound;
+ osg::Vec3d theCenterGrid;
+};
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainLayer.h
new file mode 100644
index 0000000..5f2132a
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainLayer.h
@@ -0,0 +1,191 @@
+#ifndef ossimPlanetTerrainLayer_HEADER
+#define ossimPlanetTerrainLayer_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <osg/Object>
+#include <osg/Texture>
+
+class OSSIMPLANET_DLL ossimPlanetTerrainLayer : public osg::Object
+{
+public:
+ ossimPlanetTerrainLayer()
+ :theDirtyFlag(false),
+ theMinLevel(0),
+ theMaxLevel(99999),
+ theMinFilter(osg::Texture::LINEAR),
+ theMagFilter(osg::Texture::LINEAR)
+ {
+ setThreadSafeRefUnref(true);
+ }
+
+ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
+ ossimPlanetTerrainLayer(const ossimPlanetTerrainLayer& src,
+ const osg::CopyOp& copyValue=osg::CopyOp::SHALLOW_COPY)
+ :osg::Object(src, copyValue),
+ theDirtyFlag(src.theDirtyFlag),
+ theMinLevel(src.theMinLevel),
+ theMaxLevel(src.theMaxLevel),
+ theMinFilter(src.theMinFilter),
+ theMagFilter(src.theMagFilter)
+ {
+ setThreadSafeRefUnref(true);
+ theMinLevel = src.theMinLevel;
+ theMaxLevel = src.theMaxLevel;
+ }
+
+ META_Object(ossimPlanet, ossimPlanetTerrainLayer);
+
+ virtual void dirty()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theDirtyFlag = true;
+ }
+ virtual bool isDirty()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theDirtyFlag;
+ }
+ virtual void setDirtyFlag(bool flag)
+ {
+ if(flag)
+ {
+ dirty();
+ }
+ else
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theDirtyFlag = flag;
+ }
+ }
+
+ virtual void setMinMaxLevel(ossim_uint32 minLevel,
+ ossim_uint32 maxLevel)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theMinLevel = minLevel;
+ theMaxLevel = maxLevel;
+ }
+ ossim_uint32 minLevel()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theMinLevel;
+ }
+ ossim_uint32 maxLevel()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theMaxLevel;
+ }
+ osg::Texture::FilterMode minFilter()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theMinFilter;
+ }
+ osg::Texture::FilterMode magFilter()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theMagFilter;
+ }
+ OpenThreads::Mutex& propertyMutex(){return thePropertyMutex;}
+ virtual void setRefreshFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theRefreshFlag = flag;
+ }
+ virtual bool refreshFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theRefreshFlag;
+ }
+
+protected:
+ mutable OpenThreads::Mutex thePropertyMutex;
+ bool theDirtyFlag;
+ bool theRefreshFlag;
+ ossim_uint32 theMinLevel;
+ ossim_uint32 theMaxLevel;
+ osg::Texture::FilterMode theMinFilter;
+ osg::Texture::FilterMode theMagFilter;
+};
+
+class OSSIMPLANET_DLL ossimPlanetTerrainImageLayer : public ossimPlanetTerrainLayer
+{
+public:
+ ossimPlanetTerrainImageLayer()
+ :theNoMoreDataFlag(false)
+ {
+ }
+ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
+ ossimPlanetTerrainImageLayer(const ossimPlanetTerrainImageLayer& src,
+ const osg::CopyOp& copyValue=osg::CopyOp::SHALLOW_COPY)
+ :ossimPlanetTerrainLayer(src, copyValue),
+ theNoMoreDataFlag(src.theNoMoreDataFlag)
+ {
+ if(src.theImage.valid())
+ {
+ theImage = new ossimPlanetImage(*src.theImage,
+ osg::CopyOp::DEEP_COPY_ALL);
+ }
+ }
+
+
+ META_Object(ossimPlanet, ossimPlanetTerrainImageLayer);
+
+ virtual void setImage(ossimPlanetImage* image)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theImage = image;
+ if(theImage.valid())
+ {
+ theImage->dirty();
+ }
+ theDirtyFlag = true;
+ }
+ ossimPlanetImage* cloneImage()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theImage.valid())
+ {
+ return new ossimPlanetImage(*theImage.get());
+ }
+ return 0;
+ }
+ ossimPlanetImage* image()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theImage.get();
+ }
+ const ossimPlanetImage* image()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theImage.get();
+ }
+ virtual void dirty()
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theImage.valid())
+ {
+ theImage->dirty();
+ }
+ }
+ ossimPlanetTerrainLayer::dirty();
+ }
+ ossim_uint32 modifiedCount()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(!theImage) return 0;
+ return theImage->getModifiedCount();
+ }
+ void setNoMoreDataFlag(bool flag)
+ {
+ theNoMoreDataFlag = flag;
+ }
+ bool noMoreDataFlag()const
+ {
+ return theNoMoreDataFlag;
+ }
+protected:
+ bool theNoMoreDataFlag;
+ osg::ref_ptr<ossimPlanetImage> theImage;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTechnique.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTechnique.h
new file mode 100644
index 0000000..eb1b871
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTechnique.h
@@ -0,0 +1,170 @@
+#ifndef ossimPlanetTerrainTechnique_HEADER
+#define ossimPlanetTerrainTechnique_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Referenced>
+#include <osgUtil/UpdateVisitor>
+#include <osgUtil/CullVisitor>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossimPlanet/ossimPlanetTexture2D.h>
+#include <osgUtil/GLObjectsVisitor>
+
+class ossimPlanetTerrainTile;
+class OSSIMPLANET_DLL ossimPlanetTerrainTechnique : public osg::Object
+{
+public:
+ META_Object(ossimPlanet, ossimPlanetTerrainTechnique);
+ class OSSIMPLANET_DLL CompileObjects : public osgUtil::GLObjectsVisitor
+ {
+ public:
+ CompileObjects()
+ : osgUtil::GLObjectsVisitor(COMPILE_STATE_ATTRIBUTES|COMPILE_DISPLAY_LISTS|CHECK_BLACK_LISTED_MODES)
+ {
+
+ }
+ virtual void apply(osg::Node& node);
+ virtual void apply(osg::Geode& node);
+ virtual void apply(osg::Drawable& drawable);
+ virtual void apply(osg::StateSet& stateset);
+ };
+
+ class CullCallback : public osg::NodeCallback
+ {
+ public:
+ CullCallback(){}
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ ossimPlanetTerrainTechnique* technique = dynamic_cast<ossimPlanetTerrainTechnique*>(node);
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
+ if(technique&&cv)
+ {
+ technique->cull(cv);
+ }
+ else if(node)
+ {
+ node->traverse(*nv);
+ }
+ }
+ };
+ friend class ossimPlanetTerrainTile;
+ typedef std::vector<ossimPlanetTerrainTileId> TileIdList;
+ ossimPlanetTerrainTechnique();
+ ossimPlanetTerrainTechnique(const ossimPlanetTerrainTechnique& src,
+ const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ virtual void setTerrainTile(ossimPlanetTerrainTile* tile);
+ ossimPlanetTerrainTile* terrainTile()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTerrainTileMutex);
+ return theTerrainTile;
+ }
+ const ossimPlanetTerrainTile* terrainTile() const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTerrainTileMutex);
+ return theTerrainTile;
+ }
+
+ void setGrid(ossimPlanetGrid* grid){theGrid = grid;}
+ void setModel(ossimPlanetGeoRefModel* model){theModel = model;}
+
+ const ossimPlanetGrid* grid()const
+ {
+ return theGrid.get();
+ }
+ const ossimPlanetGeoRefModel* model()const{return theModel.get();}
+
+ virtual bool isLeaf()const;
+ virtual bool areAllChildrenLeaves()const;
+ virtual void init(ossimPlanetTerrainTile* optionalParent=0);
+
+// virtual void applyImageLayer(ossim_int32 idx=-1)=0;
+// virtual void applyElevation()=0;
+
+ virtual void update(osgUtil::UpdateVisitor* nv);
+
+ virtual void cull(osgUtil::CullVisitor* nv);
+
+ /** Traverse the terrain subgraph.*/
+ virtual void traverse(osg::NodeVisitor& nv);
+
+// virtual void split(bool recurse, double availableTime=2.5);
+ virtual void childAdded(ossim_uint32 /*pos*/)
+ {
+
+ }
+
+ virtual void merge();
+
+ virtual double texturePriority()const
+ {
+ return 0.0;
+ }
+
+ virtual double elevationPriority()const
+ {
+ return texturePriority();
+ }
+
+ virtual double splitPriority()const
+ {
+ return texturePriority();
+ }
+ virtual double mergePriority()const
+ {
+ return texturePriority();
+ }
+
+ /**
+ *
+ */
+ virtual void solveTextureMatrixMappingToParent(const ossimPlanetTerrainTileId& tileId,
+ osg::Matrixd& m)const;
+ virtual void solveTextureMatrixMappingToParent(const ossimPlanetTerrainTileId& startId,
+ const ossimPlanetTerrainTileId& endId,
+ osg::Matrixd& m)const;
+
+ virtual osg::BoundingSphere computeBound() const
+ {
+ return osg::BoundingSphere(osg::Vec3d(0.0,0.0,0.0), -1);
+ }
+
+ virtual void compileGlObjects(osg::State* /*state*/)
+ {
+ // intentianally left blank
+ }
+ virtual void setImageLayerTexture(ossimPlanetTexture2D* /*texture*/,
+ ossim_uint32 /*imageLayerIdx*/)
+ {
+ // intentianally left blank
+ }
+ virtual void setElevationMeshFrom(ossimPlanetTerrainTile* /*tile*/)
+ {
+ // intentianally left blank
+ }
+ virtual ossimPlanetTexture2D* newImageLayerTexture(ossim_uint32 /*imageLayerIdx*/)
+ {
+ return 0;
+ }
+ virtual ossim_uint32 childIndex(const ossimPlanetTerrainTileId& tileId)const;
+ virtual void childTreePosition(const ossimPlanetTerrainTileId& tileId,
+ ossim_uint32& x, ossim_uint32& y)const;
+ virtual void vacantChildIds(TileIdList& ids)const;
+ virtual void releaseGLObjects(osg::State* /*state*/=0)
+ {
+
+ }
+protected:
+ virtual ~ossimPlanetTerrainTechnique();
+ mutable OpenThreads::Mutex theTerrainTileMutex;
+ /**
+ * this ossimPlanetGeoRefModel will be replaced soon with a general
+ * GeoRefModel
+ */
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+
+ osg::ref_ptr<ossimPlanetGrid> theGrid;
+ ossimPlanetTerrainTile* theTerrainTile;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTile.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTile.h
new file mode 100644
index 0000000..427a6fb
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTile.h
@@ -0,0 +1,223 @@
+#ifndef ossimPlanetTerrainTile_HEADER
+#define ossimPlanetTerrainTile_HEADER
+#include <osg/Group>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <ossimPlanet/ossimPlanetTerrainTileId.h>
+#include <ossimPlanet/ossimPlanetTerrainLayer.h>
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <osg/observer_ptr>
+#include <OpenThreads/ReadWriteMutex>
+
+class ossimPlanetTerrain;
+class OSSIMPLANET_DLL ossimPlanetTerrainTile : public osg::Group
+{
+public:
+ friend class ossimPlanetTerrain;
+
+ class MergeTestVisitor : public osg::NodeVisitor
+ {
+ public:
+ MergeTestVisitor(bool cancelScheduledTasksFlag=true)
+ :NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ theCancelScheduledTasksFlag(cancelScheduledTasksFlag),
+ theCanMergeFlag(true)
+ {
+ }
+ virtual void reset()
+ {
+ theCanMergeFlag = true;
+ }
+ virtual void apply(osg::Node& node)
+ {
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(&node);
+ if(tile)
+ {
+ if(theCancelScheduledTasksFlag)
+ {
+ tile->splitRequest()->cancel();
+ tile->elevationRequest()->cancel();
+ tile->textureRequest()->cancel();
+ }
+ if((tile->splitRequest()->referenceCount() >1)||
+ (tile->elevationRequest()->referenceCount() > 1)||
+ (tile->textureRequest()->referenceCount()>1))
+ {
+ theCanMergeFlag = false;
+ }
+ }
+
+ traverse(node);
+ }
+ bool canMerge()const{return theCanMergeFlag;}
+ protected:
+ bool theCancelScheduledTasksFlag;
+ bool theCanMergeFlag;
+ };
+ typedef std::vector<osg::ref_ptr<ossimPlanetTerrainImageLayer> > ImageLayers;
+ typedef osg::ref_ptr<ossimPlanetTerrainImageLayer> ElevationLayer;
+ typedef std::vector<osg::ref_ptr<ossimPlanetTerrainTile> > TileList;
+ ossimPlanetTerrainTile();
+ ossimPlanetTerrainTile(const ossimPlanetTerrainTileId& value);
+ virtual ~ossimPlanetTerrainTile();
+
+ virtual void init(ossimPlanetTerrainTile* optionalParentOverride=0);
+ void traverse(osg::NodeVisitor& nv);
+
+ void setTerrainTechnique(ossimPlanetTerrainTechnique* terrainTechnique);
+
+ /** Get the TerrainTechnique*/
+ ossimPlanetTerrainTechnique* terrainTechnique() { return theTerrainTechnique.get(); }
+
+ /** Get the const TerrainTechnique*/
+ const ossimPlanetTerrainTechnique* terrainTechnique() const
+ {
+ return theTerrainTechnique.get();
+ }
+ void copyCommonParameters(ossimPlanetTerrainTile* src);
+ const ossimPlanetTerrainTileId& tileId()const{return theId;}
+ void setTileId(const ossimPlanetTerrainTileId& value);
+ void setTerrain(ossimPlanetTerrain* value);
+ ossimPlanetTerrain* terrain();
+ const ossimPlanetTerrain* terrain()const;
+ ossimPlanetGrid* grid(){return theGrid.get();}
+ const ossimPlanetGrid* grid()const{return theGrid.get();}
+
+ virtual void cancelAllOperations();
+ virtual bool hasActiveOperations()const;
+
+ virtual void resetImageLayers();
+ virtual void resetElevationLayer();
+/**
+ * Will be non destructive set.
+ */
+ void setNumberOfImageLayers(ossim_uint32 n);
+ ossim_uint32 numberOfImageLayers()const;
+ bool imageLayersDirty()const;
+ ossimPlanetTerrainImageLayer* imageLayer(ossim_uint32 idx=0);
+ ossimPlanetTerrainImageLayer* elevationLayer();
+
+ ossim_int32 indexOfChild(const ossimPlanetTerrainTileId& id);
+ ossimPlanetTerrainTile* child(const ossimPlanetTerrainTileId& id);
+
+ ossimPlanetTerrainTile* parentTile();
+ const ossimPlanetTerrainTile* parentTile()const;
+
+ virtual void vacantChildIds(ossimPlanetTerrainTechnique::TileIdList& ids)const;
+ //virtual void split(bool recurse=true, double availableTime=2.5);
+ virtual void merge();
+
+ void setCulledFlag(bool culled);
+ bool culledFlag()const;
+
+ virtual osg::BoundingSphere computeBound() const;
+
+ ossimPlanetOperation* splitRequest()
+ {
+ return theSplitRequest.get();
+ }
+ const ossimPlanetOperation* splitRequest()const
+ {
+ return theSplitRequest.get();
+ }
+
+ ossimPlanetOperation* elevationRequest()
+ {
+ return theElevationRequest.get();
+ }
+
+ ossimPlanetOperation* textureRequest()
+ {
+ return theTextureRequest.get();
+ }
+ virtual void releaseGLObjects(osg::State* state=0);
+
+ /**
+ * @return the last cull time stamp.
+ */
+ ossim_float64 simTimeStamp()const
+ {
+ return theSimTimeStamp;
+ }
+
+
+ /**
+ * @return the last cull time stamp.
+ */
+ ossim_float64 timeStamp()const
+ {
+ return theTimeStamp;
+ }
+
+ /**
+ * @return the last cull frame stamp
+ */
+ ossim_int64 frameNumber()const
+ {
+ return theFrameNumber;
+ }
+
+ void updateFrameAndTimeStamps(const osg::FrameStamp* stamp)
+ {
+ if(stamp)
+ {
+ theFrameNumber = stamp->getFrameNumber();
+ theTimeStamp = stamp->getReferenceTime();
+ theSimTimeStamp = stamp->getSimulationTime();
+ }
+ }
+protected:
+ virtual void childInserted(unsigned int /*pos*/);
+
+ mutable ossimPlanetReentrantMutex thePropertyMutex;
+ ossimPlanetTerrainTileId theId;
+
+ osg::ref_ptr<ossimPlanetGrid> theGrid;
+ ossimPlanetTerrain* theTerrain;
+ osg::ref_ptr<ossimPlanetTerrainTechnique> theTerrainTechnique;
+
+ ImageLayers theImageLayers;
+ ElevationLayer theElevationLayer;
+
+ bool theCulledFlag;
+
+ /**
+ * Job interface to the split queue
+ */
+ osg::ref_ptr<ossimPlanetOperation> theSplitRequest;
+
+ /**
+ * Job interface to the texture queue
+ */
+ osg::ref_ptr<ossimPlanetOperation> theTextureRequest;
+
+ /**
+ * Job interface to the elevation queue
+ */
+ osg::ref_ptr<ossimPlanetOperation> theElevationRequest;
+
+ /**
+ * Will hold the frame stamp of the last culled visit. If it get's culled it should not update
+ * it's frame stamp
+ */
+ ossim_int64 theFrameNumber;
+
+
+ /**
+ * Will hold the time stamp of the last culled visit. If it get's culled it should not update
+ * it's time stamp
+ */
+ ossim_float64 theTimeStamp;
+
+ /**
+ * Will hold the simulation time stamp of the last culled visit. If it get's culled it should not update
+ * it's time stamp
+ */
+ ossim_float64 theSimTimeStamp;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTileId.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTileId.h
new file mode 100644
index 0000000..7aa5fb2
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTerrainTileId.h
@@ -0,0 +1,76 @@
+#ifndef ossimPlanetTerrainTileId_HEADER
+#define ossimPlanetTerrainTileId_HEADER
+#include <ossim/base/ossimConstants.h>
+#include <iostream>
+
+class OSSIMPLANET_DLL ossimPlanetTerrainTileId
+{
+public:
+ friend std::ostream& operator <<(std::ostream& out, const ossimPlanetTerrainTileId& tileid)
+ {
+ return out << "<" << tileid.theFace <<", " << tileid.theLevel << ", " << tileid.theX << ", " << tileid.theY << ">";
+ }
+ ossimPlanetTerrainTileId()
+ :theFace(0),
+ theLevel(0),
+ theX(0),
+ theY(0)
+ {
+ setId(0,0,0,0);
+ }
+ ossimPlanetTerrainTileId(ossim_uint32 face, ossim_uint32 level, ossim_uint64 x, ossim_uint64 y)
+ {
+ setId(face, level, x, y);
+ }
+ bool operator == (const ossimPlanetTerrainTileId& rhs) const
+ {
+ return (theLevel==rhs.theLevel) && (theX==rhs.theX) && (theY==rhs.theY) && (theFace == rhs.theFace);
+ }
+
+ bool operator != (const ossimPlanetTerrainTileId& rhs) const
+ {
+ return (theLevel!=rhs.theLevel) || (theX!=rhs.theX) || (theY!=rhs.theY) || (theFace != rhs.theFace);
+ }
+
+ bool operator < (const ossimPlanetTerrainTileId& rhs) const
+ {
+ if (theLevel<rhs.theLevel) return true;
+ if (theLevel>rhs.theLevel) return false;
+ if (theX<rhs.theX) return true;
+ if (theX>rhs.theX) return false;
+ if (theY<rhs.theY) return true;
+ if (theY>rhs.theY) return false;
+ return theFace<rhs.theFace;
+ }
+
+ void setId(ossim_uint32 face, ossim_uint32 level, ossim_uint64 x, ossim_uint64 y)
+ {
+ theFace = face;
+ theLevel = level;
+ theX = x;
+ theY = y;
+ }
+ void splitQuad(ossimPlanetTerrainTileId& quad00,
+ ossimPlanetTerrainTileId& quad10,
+ ossimPlanetTerrainTileId& quad11,
+ ossimPlanetTerrainTileId& quad01)
+ {
+ ossim_uint32 xOrigin=theX<<1;
+ ossim_uint32 yOrigin=theY<<1;
+
+ quad00.setId(theFace, theLevel+1, xOrigin, yOrigin);
+ quad10.setId(theFace, theLevel+1, xOrigin+1, yOrigin);
+ quad11.setId(theFace, theLevel+1, xOrigin+1, yOrigin+1);
+ quad01.setId(theFace, theLevel+1, xOrigin, yOrigin+1);
+ }
+ const ossim_uint32& level()const{return theLevel;}
+ const ossim_uint64& x()const{return theX;}
+ const ossim_uint64& y()const{return theY;}
+ const ossim_uint32& face()const{return theFace;}
+ ossim_uint32 theFace;
+ ossim_uint32 theLevel;
+ ossim_uint64 theX;
+ ossim_uint64 theY;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTexture2D.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTexture2D.h
new file mode 100644
index 0000000..5a6428c
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTexture2D.h
@@ -0,0 +1,34 @@
+#ifndef ossimPlanetTexture2D_HEADER
+#define ossimPlanetTexture2D_HEADER
+#include <osg/Texture2D>
+#include <osg/State>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPlanet/ossimPlanetTerrainTileId.h>
+
+class ossimPlanetImage;
+class OSSIMPLANET_DLL ossimPlanetTexture2D : public osg::Texture2D
+{
+public:
+ ossimPlanetTexture2D(const ossimPlanetTerrainTileId& id=ossimPlanetTerrainTileId(0,0,0,0));
+ ossimPlanetTexture2D(osg::Image* image,
+ const ossimPlanetTerrainTileId& id=ossimPlanetTerrainTileId(0,0,0,0));
+ ossimPlanetTexture2D(ossimPlanetImage* image);
+
+ /** Copy constructor using CopyOp to manage deep vs shallow copy. */
+ ossimPlanetTexture2D(const ossimPlanetTexture2D& text,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+ virtual ~ossimPlanetTexture2D();
+
+ void setImage(ossimPlanetImage* image);
+ const ossimPlanetTerrainTileId& tileId()const;
+ void setId(const ossimPlanetTerrainTileId& id);
+
+protected:
+ ossimPlanetTerrainTileId theTileId;
+ ossim_uint32 theFace;
+ ossim_uint32 theLevel;
+ ossim_uint64 theRow;
+ ossim_uint64 theCol;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayer.h
new file mode 100644
index 0000000..b585eff
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayer.h
@@ -0,0 +1,380 @@
+#ifndef ossimPlanetTextureLayer_HEADER
+#define ossimPlanetTextureLayer_HEADER
+#include <osg/Referenced>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimId.h>
+#include "ossimPlanetExport.h"
+#include "ossimPlanetImage.h"
+#include "ossimPlanetGridUtility.h"
+#include <ossimPlanet/ossimPlanetId.h>
+#include <ossim/base/ossimDate.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossimPlanet/ossimPlanetExtents.h>
+#include <ossimPlanet/ossimPlanetConstants.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <vector>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+
+class ossimPlanetTextureLayerGroup;
+
+class ossimPlanetTextureLayer;
+class OSSIMPLANET_DLL ossimPlanetTextureLayerCallback : public ossimPlanetCallback
+{
+public:
+ ossimPlanetTextureLayerCallback(){}
+
+ virtual void layerAdded(osg::ref_ptr<ossimPlanetTextureLayer> /*layer*/)
+ {
+ }
+ virtual void layerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> /*layer*/,
+ osg::ref_ptr<ossimPlanetTextureLayer> /*parent*/)
+ {
+ }
+ virtual void refreshExtent(osg::ref_ptr<ossimPlanetExtents> /*extent*/)
+ {
+ }
+ virtual void propertyChanged(const ossimString& /*name*/,
+ const ossimPlanetTextureLayer* /*object*/){}
+
+};
+
+class ossimPlanetTextureLayerRaiseCallback;
+
+class OSSIMPLANET_DLL ossimPlanetTextureLayer : public osg::Referenced,
+ public ossimPlanetCallbackListInterface<ossimPlanetTextureLayerCallback>
+{
+public:
+ friend class ossimPlanetTextureLayerRaiseCallback;
+ class OSSIMPLANET_DLL Stats : public osg::Referenced
+ {
+ public:
+ Stats()
+ :osg::Referenced(),
+ theTotalTextureSize(0),
+ theBytesTransferred(0)
+ {
+ }
+ Stats(const Stats& src)
+ :osg::Referenced(),
+ theTotalTextureSize(src.theTotalTextureSize),
+ theBytesTransferred(src.theBytesTransferred)
+ {
+
+ }
+
+ Stats* clone()const
+ {
+ return new Stats(*this);
+ }
+
+ const ossim_uint64& totalTextureSize()const
+ {
+ return theTotalTextureSize;
+ }
+ void setTotalTextureSize(const ossim_uint64& size)
+ {
+ theTotalTextureSize = size;
+ }
+
+ const ossim_uint64& bytesTransferred()const
+ {
+ return theBytesTransferred;
+ }
+ void setBytesTransferred(ossim_uint64 amountTransferred)
+ {
+ theBytesTransferred = amountTransferred;
+ }
+ protected:
+
+ ossim_uint64 theTotalTextureSize;
+ ossim_uint64 theBytesTransferred;
+ };
+/* typedef std::vector<osg::ref_ptr<ossimPlanetTextureLayer::Callback> > CallbackList; */
+ typedef std::vector<ossimPlanetTextureLayerGroup*> ossimPlanetTextureLayerParentList;
+ typedef std::vector<unsigned char> TransparentColorType;
+
+
+ ossimPlanetTextureLayer();
+ ossimPlanetTextureLayer(const ossimPlanetTextureLayer& src);
+ virtual ~ossimPlanetTextureLayer();
+ virtual ossimPlanetTextureLayer* dup()const=0;
+ virtual ossimPlanetTextureLayer* dupType()const=0;
+ virtual ossimString getClassName()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents()=0;
+
+ void addBytesTransferredStat(ossim_uint64 bytesTransferred)const;
+ virtual void updateStats()const=0;
+ /**
+ * Since theStateCode is a utility / mutable variable and is updated during
+ * constant and non constant access we will make this a const on ll other non mutable
+ * variables.
+ */
+ void clearState(ossimPlanetTextureLayerStateCode stateCode=ossimPlanetTextureLayer_ALL)const;
+
+ /**
+ * Since theStateCode is a utility / mutable variable and is updated during
+ * constant and non constant access we will make this a const on ll other non mutable
+ * variables.
+ */
+ void setState(ossimPlanetTextureLayerStateCode stateCode)const;
+
+ ossimPlanetTextureLayerStateCode getStateCode()const;
+ bool isStateSet(ossimPlanetTextureLayerStateCode)const;
+
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid)=0;
+
+ /**
+ * We will supply an optional padding value. This is a request and if the request occured successfully
+ * then the padding variable will be set in the resulting image result.
+ *
+ *
+ */
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0)=0;
+ /**
+ * Deprecated. Will be replaced with the new tiling grid interface
+ */
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)=0;
+
+ void dirtyExtents();
+ void dirtyStats();
+ void setDirtyExtentsFlag(bool flag);
+ const osg::ref_ptr<ossimPlanetTextureLayer::Stats> getStats()const;
+ osg::ref_ptr<ossimPlanetTextureLayer::Stats> getStats();
+ const osg::ref_ptr<ossimPlanetExtents> getExtents()const;
+ osg::ref_ptr<ossimPlanetExtents> getExtents();
+ virtual void setExtents (osg::ref_ptr<ossimPlanetExtents> extents);
+
+ virtual const osg::ref_ptr<ossimPlanetLookAt> getLookAt()const;
+ virtual void setLookAt(osg::ref_ptr<ossimPlanetLookAt> lookAt);
+
+ virtual void getDateRange(ossimDate& minDate,
+ ossimDate& maxDate)const;
+ /**
+ * Approximate length in meters of the hypotneus. Just uses the getExtents
+ * and ten approximates a meter gsd from the degree bounds.
+ */
+ virtual double getApproximateHypotneusLength()const;
+
+ /**
+ * Will return the center lat lon and the approximate hypotneus length in meters.
+ */
+ virtual void getCenterLatLonLength(double& centerLat,
+ double& centerLon,
+ double& length)const;
+ virtual ossimPlanetTextureLayerGroup* asGroup();
+ virtual const ossimPlanetTextureLayerGroup* asGroup()const;
+ ossimPlanetTextureLayerGroup* getParent(ossim_uint32 idx);
+ const ossimPlanetTextureLayerGroup* getParent(ossim_uint32 idx)const;
+ ossimPlanetTextureLayerGroup* parent(ossim_uint32 idx);
+ const ossimPlanetTextureLayerGroup* parent(ossim_uint32 idx)const;
+ ossim_uint32 getNumberOfParents();
+ bool hasParent(ossimPlanetTextureLayerGroup* parent)const;
+ void setParent(ossimPlanetTextureLayer* parent);
+ const ossimString& id()const;
+ void setId(const ossimString& id);
+ virtual void setEnableFlag(bool flag);
+ bool enableFlag()const;
+ bool getEnableFlag()const;
+
+ void setName(const ossimString& name);
+ const ossimString& getName()const;
+ const ossimString& name()const;
+
+ void setDescription(const ossimString& description);
+ const ossimString& getDescription()const;
+ const ossimString& description()const;
+
+ void setTransparentColorFlag(bool flag);
+ bool getTransparentColorFlag()const;
+ const TransparentColorType& getTransparentColor()const;
+ void setTransparentColor(unsigned int r,
+ unsigned int g,
+ unsigned int b);
+
+ bool insertAlpha(osg::ref_ptr<ossimPlanetImage> texture)const;
+ bool insertAlpha(osg::ref_ptr<ossimPlanetImage> texture,
+ float initialAlphaValue)const;
+ void addTransparent(osg::ref_ptr<ossimPlanetImage> texture)const;
+
+ void detachFromParents();
+ void addParent(ossimPlanetTextureLayerGroup* parent);
+ void removeParent(ossimPlanetTextureLayerGroup* parent);
+
+ virtual void setFilterType(const ossimString& filterType);
+ virtual const ossimString& getFilterTypeAsString()const;
+/* void addCallback(osg::ref_ptr<ossimPlanetTextureLayer::Callback> callback); */
+/* void removeCallback(osg::ref_ptr<ossimPlanetTextureLayer::Callback> callback); */
+
+ OpenThreads::Mutex& mutex();
+
+ virtual void getMetadata(ossimRefPtr<ossimXmlNode> metadata)const;
+ virtual ossimRefPtr<ossimXmlNode> saveXml(bool recurseFlag=true)const;
+ virtual bool loadXml(ossimRefPtr<ossimXmlNode> node);
+
+
+ // all notification methods are propagated if parent texture layers are listening to child layers.
+ //
+ void notifyRefreshExtent(osg::ref_ptr<ossimPlanetExtents> extent);
+ void notifyLayerAdded(osg::ref_ptr<ossimPlanetTextureLayer> layer);
+ void notifyLayerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ osg::ref_ptr<ossimPlanetTextureLayer> parent);
+ void notifyPropertyChanged(const ossimString& name,
+ const ossimPlanetTextureLayer* layer)const;
+
+ virtual void resetLookAt();
+
+ virtual ossimPlanetTextureLayer* findLayerByName(const ossimString& layerName,
+ bool recurseFlag=false);
+ virtual const ossimPlanetTextureLayer* findLayerByName(const ossimString& layerName,
+ bool recurseFlag=false)const;
+
+ virtual ossimPlanetTextureLayer* findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId);
+ virtual const ossimPlanetTextureLayer* findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId)const;
+
+ virtual ossimPlanetTextureLayer* findLayerById(const ossimString& layerId,
+ bool recurseFlag=false);
+ virtual const ossimPlanetTextureLayer* findLayerById(const ossimString& layerId,
+ bool recurseFlag=false)const;
+
+ void remove();
+
+
+ ossim_float32 brightness()const;
+ ossim_float32 contrast()const;
+ ossim_float32 opacity()const;
+
+ /**
+ * Allows one to enable brightness contrast settings.
+ */
+ void setBrightnessContrast(ossim_float32 brightnessValue,
+ ossim_float32 contrastValue,
+ bool notifyFlag = true);
+ /**
+ * Allows one to enable brightness settings.
+ */
+ void setBrightness(ossim_float32 brightnessValue, bool notifyFlag=true);
+ /**
+ * Allows one to enable contrast settings.
+ */
+ void setContrast(ossim_float32 contrastValue, bool notifyFlag = true);
+
+ /**
+ * Allows one to set the opacity.
+ *
+ * @param opacityValue value of 1.0 is fully opaque and a value of 0 is fully transparent
+ */
+ void setOpacity(ossim_float32 opacityValue, bool notifyFlag = true);
+
+protected:
+ ossimPlanetImage* applyBrightnessContrast(ossimPlanetImage* image, bool duplicateFlag=true)const;
+ virtual void mergeImage(ossimPlanetImage* result,
+ const ossimPlanetImage* source,
+ ossim_float32 sourceOpacity=1.0)const;
+
+ void convertToOsg(ossimImageData* data,
+ ossimPlanetImage* image)const;
+ void convertToOsg(ossimImageData* data,
+ ossimPlanetImage* image,
+ const osg::Vec2d& ulInput,
+ const osg::Vec2d& /*urInput*/,
+ const osg::Vec2d& lrInput,
+ const osg::Vec2d& /*llInput*/,
+ ossimPlanetGrid::ModelPoints& outputGridPoints,
+ ossim_uint32 outputWidth,
+ ossim_uint32 outputHeight)const;
+
+ void convertToOsg(ossimImageData* data,
+ ossimPlanetImage* image,
+ const osg::Vec2d& ulInput,
+ const osg::Vec2d& urInput,
+ const osg::Vec2d& lrInput,
+ const osg::Vec2d& llInput,
+ std::vector<ossimPlanetGridUtility::GridPoint>& outputGridPoints,
+ const ossimPlanetGridUtility& utility,
+ ossim_uint32 outputWidth,
+ ossim_uint32 outputHeight)const;
+
+ ossimString theName;
+ ossimString theDescription;
+ ossimString theId;
+ ossimPlanetTextureLayerParentList theParentList;
+ mutable osg::ref_ptr<ossimPlanetExtents> theExtents;
+ mutable osg::ref_ptr<ossimPlanetLookAt> theLookAt;
+
+ bool theEnableFlag;
+ bool theTransparentColorFlag;
+ TransparentColorType theTransparentColorVector; // [0] = r, [1] = g, [2] = b
+ ossimString theFilterType;
+ mutable ossimPlanetReentrantMutex thePropertyMutex;
+ mutable ossimPlanetReentrantMutex theMutex;
+/* mutable OpenThreads::Mutex theCallbackMutex; */
+ mutable bool theDirtyExtentsFlag;
+ mutable bool theDirtyStatsFlag;
+ mutable osg::ref_ptr<Stats> theStats;
+ mutable ossimPlanetTextureLayerStateCode theStateCode;
+
+ ossim_float32 theBrightness;
+ ossim_float32 theContrast;
+
+ ossim_float32 theOpacity;
+/* ossimPlanetTextureLayer::CallbackList theCallbackList; */
+
+};
+
+class OSSIMPLANET_DLL ossimPlanetTextureLayerRaiseCallback : public ossimPlanetTextureLayerCallback
+{
+public:
+ ossimPlanetTextureLayerRaiseCallback(ossimPlanetTextureLayer* parentLayer):theLayer(parentLayer){}
+ ossimPlanetTextureLayer* layer(){return theLayer;}
+ void setLayer(ossimPlanetTextureLayer* l){theLayer = l;}
+
+ virtual void layerAdded(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyLayerAdded(layer.get());
+ }
+ }
+ virtual void layerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ osg::ref_ptr<ossimPlanetTextureLayer> parent)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyLayerRemoved(layer, parent);
+ }
+ }
+ virtual void refreshExtent(osg::ref_ptr<ossimPlanetExtents> extent)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyRefreshExtent(extent);
+ }
+ }
+ virtual void propertyChanged(const ossimString& name,
+ const ossimPlanetTextureLayer* object)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyPropertyChanged(name, object);
+ }
+ }
+
+protected:
+ ossimPlanetTextureLayer* theLayer;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerFactory.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerFactory.h
new file mode 100644
index 0000000..7007e43
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerFactory.h
@@ -0,0 +1,19 @@
+#ifndef ossimPlanetTextureLayerFactory_HEADER
+#define ossimPlanetTextureLayerFactory_HEADER
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetTextureLayerFactory : public osg::Referenced
+{
+public:
+ virtual osg::ref_ptr<ossimPlanetTextureLayer> createLayer(const ossimString& name, bool openAllEntriesFlag=true)const=0;
+
+protected:
+ ossimPlanetTextureLayerFactory(){}
+ ossimPlanetTextureLayerFactory(const ossimPlanetTextureLayerFactory&):osg::Referenced(){}
+ const ossimPlanetTextureLayerFactory& operator = (const ossimPlanetTextureLayerFactory& /*src*/){return *this;}
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerGroup.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerGroup.h
new file mode 100644
index 0000000..2053af8
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerGroup.h
@@ -0,0 +1,115 @@
+#ifndef ossimPlanetTextureLayerGroup_HEADER
+#define ossimPlanetTextureLayerGroup_HEADER
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <vector>
+#include <OpenThreads/ScopedLock>
+#include <OpenThreads/ReentrantMutex>
+
+class OSSIMPLANET_DLL ossimPlanetTextureLayerGroup : public ossimPlanetTextureLayer
+{
+public:
+ ossimPlanetTextureLayerGroup();
+ ossimPlanetTextureLayerGroup(const ossimPlanetTextureLayerGroup& src);
+ ~ossimPlanetTextureLayerGroup();
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimString getClassName()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void resetStats()const;
+ virtual void updateStats()const;
+
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+
+ virtual ossimPlanetTextureLayerGroup* asGroup();
+ virtual const ossimPlanetTextureLayerGroup* asGroup()const;
+ virtual bool swapLayers(ossim_uint32 idx1, ossim_uint32 idx2, bool notifyFlag=true);
+ virtual bool swapLayers(osg::ref_ptr<ossimPlanetTextureLayer> layer1,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer2,
+ bool notifyFlag=true);
+ virtual bool replaceLayer(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag = true);
+
+ virtual bool addTop(osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag=true);
+ virtual bool addBeforeIdx(ossim_uint32 idx, osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag=true);
+ virtual bool addBeforeLayer(const osg::ref_ptr<ossimPlanetTextureLayer> beforeLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd, bool notifyFlag=true);
+ virtual bool addAfterIdx(ossim_int32 idx, osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag=true);
+ virtual bool addAfterLayer(const osg::ref_ptr<ossimPlanetTextureLayer> afterLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd, bool notifyFlag=true);
+ virtual bool addBottom(osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag=true);
+ osg::ref_ptr<ossimPlanetTextureLayer> removeLayer(ossim_uint32 idx, bool notifyFlag=true);
+ void removeLayers(ossim_uint32 idx, ossim_uint32 length=1, bool notifyFlag=true);
+ bool removeLayer(osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag=true);
+
+ ossim_int32 findLayerIndex(osg::ref_ptr<ossimPlanetTextureLayer> layer)const;
+ bool containsLayer(osg::ref_ptr<ossimPlanetTextureLayer> layer)const;
+
+ ossim_uint32 numberOfLayers()const;
+ const osg::ref_ptr<ossimPlanetTextureLayer> layer(ossim_uint32 idx)const;
+ osg::ref_ptr<ossimPlanetTextureLayer> layer(ossim_uint32 idx);
+
+ virtual ossimPlanetTextureLayer* findLayerByName(const ossimString& layerName,
+ bool recurseFlag=false);
+ virtual const ossimPlanetTextureLayer* findLayerByName(const ossimString& layerName,
+ bool recurseFlag=false)const;
+
+ virtual ossimPlanetTextureLayer* findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId);
+ virtual const ossimPlanetTextureLayer* findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId)const;
+ virtual ossimPlanetTextureLayer* findLayerById(const ossimString& layerId,
+ bool recurseFlag=false);
+ virtual const ossimPlanetTextureLayer* findLayerById(const ossimString& layerId,
+ bool recurseFlag=false)const;
+
+ /**
+ * The empty tile color is used to return a tile that has color if there is
+ * no texture in the group. The color is a normalized float vector and the normal
+ * use is to pass in (osg::Vec4f(1.0,1.0,1.0,1.0),0). This will enable the color if
+ * the level passed in is >= 0.
+ */
+ void setFillNullOrEmptyTileMaxLevel(ossim_int32 maxLevel=0);
+
+ /**
+ * Set background fill color for partial tiles. If a tile is partial it
+ * will fill any invalid color with this value.
+ */
+ void setBackgroundColor(const osg::Vec4f& color);
+ void setFillTranslucentPixelsWithBackground(bool on=true);
+
+ virtual void sortByGsd();
+ virtual ossimRefPtr<ossimXmlNode> saveXml(bool recurseFlag=true)const;
+ virtual bool loadXml(ossimRefPtr<ossimXmlNode> node);
+
+protected:
+ bool containsLayerNoMutex(osg::ref_ptr<ossimPlanetTextureLayer> layer)const;
+ bool removeLayerNoMutex(osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag);
+ osg::ref_ptr<ossimPlanetTextureLayer> removeLayerNoMutex(ossim_uint32 idx, bool notifyFlag);
+ std::vector<osg::ref_ptr<ossimPlanetTextureLayer> > removeLayersNoMutex(ossim_uint32 idx, ossim_uint32 length=1, bool notifyFlag=true);
+ ossim_int32 findLayerIndexNoMutex(osg::ref_ptr<ossimPlanetTextureLayer> layer)const;
+
+ mutable OpenThreads::Mutex theChildrenListMutex;
+ std::vector<osg::ref_ptr<ossimPlanetTextureLayer> > theChildrenList;
+ osg::ref_ptr<ossimPlanetTextureLayerCallback> theChildListener;
+
+ osg::Vec4f theBackgroundColor;
+ ossim_int32 theFillEmptyNullTileMaxLevel;
+ bool theFillTranslucentPixelsWithBackgroundEnabled;
+
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerRegistry.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerRegistry.h
new file mode 100644
index 0000000..1dd3e3e
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTextureLayerRegistry.h
@@ -0,0 +1,40 @@
+#ifndef ossimPlanetTextureLayerRegistry_HEADER
+#define ossimPlanetTextureLayerRegistry_HEADER
+#include <OpenThreads/ReadWriteMutex>
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetTextureLayerFactory.h>
+
+class OSSIMPLANET_DLL ossimPlanetTextureLayerRegistry : public osg::Referenced
+{
+public:
+ ossimPlanetTextureLayerRegistry();
+ virtual ~ossimPlanetTextureLayerRegistry();
+ static ossimPlanetTextureLayerRegistry* instance();
+
+ void registerFactory(ossimPlanetTextureLayerFactory* factory);
+ void registerFactoryToFront(ossimPlanetTextureLayerFactory* factory);
+ void unregisterFactory(ossimPlanetTextureLayerFactory* factory);
+ /**
+ * The passed in string could be a WMS http string, keyword list
+ * describing archives or a local image file, .. etc. A layer will be returned.
+ *
+ * Note this layer could be a grouped layer. For instance. An image may have multiple
+ * handlers and will return a group of all images.
+ *
+ */
+ osg::ref_ptr<ossimPlanetTextureLayer> createLayer(const ossimString& name, bool openAllEntriesFlag=true)const;
+
+
+protected:
+ ossimPlanetTextureLayerRegistry(const ossimPlanetTextureLayerRegistry& /*src*/):osg::Referenced(){}
+ const ossimPlanetTextureLayerRegistry& operator = (const ossimPlanetTextureLayerRegistry& /*src*/){return *this;}
+ bool containsFactory(ossimPlanetTextureLayerFactory* factory)const;
+
+ static ossimPlanetTextureLayerRegistry* theInstance;
+ std::vector<ossimPlanetTextureLayerFactory* > theFactoryList;
+ mutable OpenThreads::ReadWriteMutex theFactoryListMutex;
+ mutable bool destroyingFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetThread.h b/ossimPlanet/include/ossimPlanet/ossimPlanetThread.h
new file mode 100644
index 0000000..dec043b
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetThread.h
@@ -0,0 +1,30 @@
+#ifndef ossimPlanetThread_HEADER
+#define ossimPlanetThread_HEADER
+#include <OpenThreads/Thread>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include "ossimPlanetThreadImp.h"
+#include "ossimPlanetExport.h"
+
+class ossimPlanetThreadPool;
+class OSSIMPLANET_DLL ossimPlanetThread : public osg::Referenced,
+ public OpenThreads::Thread
+{
+public:
+ ossimPlanetThread();
+ virtual void run();
+ virtual int cancel();
+ virtual void updateThreadBlock();
+ void setImplementation(ossimPlanetThreadImp* implementation);
+ void setThreadPool(ossimPlanetThreadPool* threadPool);
+ ossimPlanetThreadImp* implementation();
+ const ossimPlanetThreadImp* implementation()const;
+ void setRetainThreadFlag(bool flag);
+protected:
+ ossimPlanetThreadImp* theImplementation;
+ ossimPlanetThreadPool* theThreadPool;
+ bool theRetainThreadFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetThreadImp.h b/ossimPlanet/include/ossimPlanet/ossimPlanetThreadImp.h
new file mode 100644
index 0000000..8d44006
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetThreadImp.h
@@ -0,0 +1,38 @@
+#ifndef ossimPlanetThreadImp_HEADER
+#define ossimPlanetThreadImp_HEADER
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include "ossimPlanetExport.h"
+#include "ossimPlanetRefBlock.h"
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+class ossimPlanetThread;
+class OSSIMPLANET_DLL ossimPlanetThreadImp
+{
+public:
+ ossimPlanetThreadImp()
+ :theThread(0),
+ theDoneFlag(false)
+ {
+ }
+ virtual ~ossimPlanetThreadImp();
+ virtual void setThread(ossimPlanetThread* thread)
+ {
+ theThread = thread;
+ }
+ ossimPlanetThread* thread()
+ {
+ return theThread;
+ }
+ virtual void run()=0;
+ virtual int cancel();
+ virtual void threadPooled();
+ virtual void setDoneFlag(bool flag);
+ virtual bool doneFlag()const;
+ virtual void updateThreadBlock();
+protected:
+ mutable ossimPlanetReentrantMutex theImpMutex;
+ ossimPlanetThread* theThread;
+ bool theDoneFlag;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetThreadPool.h b/ossimPlanet/include/ossimPlanet/ossimPlanetThreadPool.h
new file mode 100644
index 0000000..6ee458c
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetThreadPool.h
@@ -0,0 +1,32 @@
+#ifndef ossimPlanetThreadPool_HEADER
+#define ossimPlanetThreadPool_HEADER
+#include <vector>
+#include <OpenThreads/Thread>
+#include <ossimPlanet/ossimPlanetReentrantMutex.h>
+#include <osg/Referenced>
+#include <osg/ref_ptr>
+#include "ossimPlanetExport.h"
+
+class ossimPlanetThread;
+
+class OSSIMPLANET_DLL ossimPlanetThreadPool : public osg::Referenced
+{
+public:
+ static osg::ref_ptr<ossimPlanetThreadPool> instance();
+ void makeAvailable(osg::ref_ptr<ossimPlanetThread> thread);
+ osg::ref_ptr<ossimPlanetThread> nextAvailable();
+ static void setMaxThread(int maxThreads);
+
+protected:
+ ossimPlanetThreadPool();
+
+ unsigned int totalThreads()const;
+ std::vector<osg::ref_ptr<ossimPlanetThread> > theAvailableList;
+ std::vector<osg::ref_ptr<ossimPlanetThread> > theUnavailableList;
+ ossimPlanetReentrantMutex theListMutex;
+ static unsigned int theMaxThreads;
+ static osg::ref_ptr<ossimPlanetThreadPool> theInstance;
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetTileRequest.h b/ossimPlanet/include/ossimPlanet/ossimPlanetTileRequest.h
new file mode 100644
index 0000000..7604a12
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetTileRequest.h
@@ -0,0 +1,256 @@
+#ifndef ossimPlanetTileRequest_HEADER
+#define ossimPlanetTileRequest_HEADER
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <queue>
+#include <osg/observer_ptr>
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossimPlanet/ossimPlanetGridUtility.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <osgUtil/IncrementalCompileOperation>
+class ossimPlanetTerrainTile;
+class ossimPlanetTerrain;
+
+class OSSIMPLANET_DLL ossimPlanetTileRequest : public ossimPlanetOperation
+{
+public:
+ struct SortFunctor
+ {
+ bool operator() (const osg::ref_ptr<ossimPlanetOperation>& lhs,
+ const osg::ref_ptr<ossimPlanetOperation>& rhs) const
+ {
+ return (lhs->priority()>rhs->priority());
+ }
+ bool operator() (const osg::ref_ptr<ossimPlanetTileRequest>& lhs,
+ const osg::ref_ptr<ossimPlanetTileRequest>& rhs) const
+ {
+ return (lhs->priority()>rhs->priority());
+ }
+ };
+ typedef std::queue<osg::ref_ptr<ossimPlanetTileRequest> > Queue;
+ typedef std::list<osg::ref_ptr<ossimPlanetTileRequest> > List;
+ typedef std::vector<osg::ref_ptr<ossimPlanetTileRequest> > Vector;
+ typedef std::set< osg::ref_ptr<osg::Texture> > TextureSetList;
+ typedef std::set< osg::ref_ptr<osg::Drawable> > DrawableList;
+ typedef std::set< osg::ref_ptr<osg::VertexBufferObject> > VertexBufferList;
+ struct DataToCompile
+ {
+ TextureSetList textures;
+ VertexBufferList vbos;
+ };
+
+ class FindCompileableGLObjectsVisitor : public osg::NodeVisitor
+ {
+ public:
+ FindCompileableGLObjectsVisitor(DataToCompile& dataToCompile,
+ ossimPlanetTerrain* terrain,
+ ossim_uint32 context):
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ theDataToCompile(dataToCompile),
+ theTerrain(terrain),
+ theContextId(context)
+ {
+ }
+ virtual void apply(osg::Node& node);
+ virtual void apply(osg::Geode& geode);
+ inline void apply(osg::StateSet* stateset);
+ inline void apply(osg::Drawable* drawable);
+
+ protected:
+ ossimPlanetTileRequest::DataToCompile& theDataToCompile;
+ const ossimPlanetTerrain* theTerrain;
+ std::set<osg::ref_ptr<osg::Texture> > theTextureSet;
+ std::set<osg::ref_ptr<osg::Drawable> > theDrawableSet;
+ ossim_uint32 theContextId;
+ };
+
+ ossimPlanetTileRequest()
+ {
+ setThreadSafeRefUnref(true);
+ }
+ ossimPlanetTileRequest(ossimPlanetTerrainTile* tile);
+ virtual void setTile(ossimPlanetTerrainTile* tile);
+ ossimPlanetTerrainTile* tile();
+ const ossimPlanetTerrainTile* tile()const;
+ bool needsToCompile()const
+ {
+ return true;
+ }
+ ossim_int32 frameNumberOfLastRequest()const{return theFrameNumberLastRequest;}
+ void setFrameNumberOfLastRequest(ossim_int32 num)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFrameNumberLastRequest = num;
+ }
+ bool isRequestCurrent(ossim_int32 frameNumber)const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return ((frameNumber-theFrameNumberLastRequest)<=1);
+ }
+ void setTimestampFirstRequest(double timeStamp)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theTimestampFirstRequest = timeStamp;
+ theTimestampLastRequest = timeStamp;
+ }
+ double timeStampFirstRequest()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theTimestampFirstRequest;
+ }
+ void setTimestampLastRequest(double timeStamp)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theTimestampLastRequest = timeStamp;
+ }
+ double timestampLastRequest()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theTimestampLastRequest;
+ }
+ virtual void applyToGraph()
+ {
+
+ }
+ virtual bool compileObjects(osg::RenderInfo& renderInfo,//osg::State* s,
+ double availableTimeInSeconds=9999999);
+ virtual bool populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet);
+protected:
+ mutable OpenThreads::Mutex thePropertyMutex;
+ ossim_int32 theFrameNumberFirstRequest;
+ double theTimestampFirstRequest;
+ ossim_int32 theFrameNumberLastRequest;
+ ossim_float64 theTimestampLastRequest;
+ ossimPlanetTerrainTileId theTileId;
+ osg::observer_ptr<ossimPlanetTerrainTile> theTile;
+ osg::observer_ptr<ossimPlanetTerrain> theTerrain;
+ DataToCompile theDataToCompile;
+};
+
+class OSSIMPLANET_DLL ossimPlanetSplitRequest : public ossimPlanetTileRequest
+{
+public:
+ ossimPlanetSplitRequest(){}
+ ossimPlanetSplitRequest(ossimPlanetTerrainTile* tile);
+
+ virtual void run();
+ virtual void applyToGraph();
+ virtual bool compileObjects(osg::RenderInfo& renderInfo,//osg::State* s,
+ double availableTimeInSeconds=9999999);
+ virtual bool populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet);
+ virtual void setTile(ossimPlanetTerrainTile* tile);
+protected:
+ ossimPlanetTerrainTechnique::TileIdList theNeededChildrenList;
+ std::vector<osg::ref_ptr<ossimPlanetTerrainTile> > theNewTiles;
+};
+
+class OSSIMPLANET_DLL ossimPlanetTextureRequest : public ossimPlanetTileRequest
+{
+public:
+ ossimPlanetTextureRequest();
+ ossimPlanetTextureRequest(ossimPlanetTerrainTile* tile,
+ ossim_uint32 imageLayerIdx);
+ virtual void run();
+ virtual void applyToGraph();
+ void setImageLayerIdx(ossim_uint32 idx)
+ {
+ std::vector<ossim_uint32> idxValues;
+ idxValues.push_back(idx);
+ setTextureLayerIndices(idxValues);
+ }
+ void setTextureLayerIndices(const std::vector<ossim_uint32>& values);
+
+ virtual bool compileObjects(osg::RenderInfo& renderInfo,//osg::State* s,
+ double availableTimeInSeconds=9999999);
+ virtual bool populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet);
+protected:
+ class Result
+ {
+ public:
+ osg::ref_ptr<ossimPlanetTexture2D> theTexture;
+ osg::ref_ptr<ossimPlanetImage> theImage;
+ };
+ typedef std::map<ossim_uint32, Result> TextureResultMap;
+ TextureResultMap theResultList;
+};
+
+class OSSIMPLANET_DLL ossimPlanetElevationRequest : public ossimPlanetTileRequest
+{
+public:
+ ossimPlanetElevationRequest();
+ ossimPlanetElevationRequest(ossimPlanetTerrainTile* tile,
+ ossim_uint32 width,
+ ossim_uint32 height);
+ virtual void run();
+ virtual bool compileObjects(osg::RenderInfo& renderInfo,//osg::State* s,
+ double availableTimeInSeconds=9999999);
+ virtual bool populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet);
+ virtual void applyToGraph();
+protected:
+ osg::ref_ptr<ossimPlanetTerrainTile> theNewMesh;
+ osg::ref_ptr<ossimPlanetImage> theImage;
+};
+
+class OSSIMPLANET_DLL ossimPlanetTileRequestQueue : public ossimPlanetOperationQueue
+{
+public:
+ ossimPlanetTileRequestQueue(bool sortFlag=true);
+ void sort();
+ virtual void add(ossimPlanetTileRequest* request);
+ virtual osg::ref_ptr<ossimPlanetOperation> nextOperation(bool blockIfEmptyFlag=true);
+ void setCurrentFrameNumber(ossim_int32 num)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRequestQueueMutex);
+ theCurrentFrameNumber = num;
+ }
+ void setSortFlag(bool flag)
+ {
+ theSortFlag = flag;
+ }
+ bool sortFlag()const
+ {
+ return theSortFlag;
+ }
+protected:
+ OpenThreads::Mutex theRequestQueueMutex;
+ ossim_int32 theCurrentFrameNumber;
+ bool theSortFlag;
+};
+
+class OSSIMPLANET_DLL ossimPlanetTileRequestThreadQueue : public ossimPlanetOperationThreadQueue
+{
+public:
+ ossimPlanetTileRequestThreadQueue ()
+ :ossimPlanetOperationThreadQueue()
+ {
+ setOperationQueue(new ossimPlanetTileRequestQueue());
+ }
+ virtual ~ossimPlanetTileRequestThreadQueue(){}
+ virtual void add(ossimPlanetTileRequest* request);
+ virtual void run();
+ void setCurrentFrameNumber(ossim_int32 num)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRequestThreadQueueMutex);
+ theCurrentFrameNumber = num;
+ ossimPlanetTileRequestQueue* tileQueue = dynamic_cast<ossimPlanetTileRequestQueue*>(operationQueue());
+ if(tileQueue)
+ {
+ tileQueue->setCurrentFrameNumber(num);
+ }
+ }
+ ossim_int32 currentFrameNumber()const
+ {
+ return theCurrentFrameNumber;
+ }
+ //void applyToGraph(double availableTime=2.5);
+protected:
+ OpenThreads::Mutex theRequestThreadQueueMutex;
+ ossim_int32 theCurrentFrameNumber;
+};
+
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetUtility.h b/ossimPlanet/include/ossimPlanet/ossimPlanetUtility.h
new file mode 100644
index 0000000..9f1abed
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetUtility.h
@@ -0,0 +1,29 @@
+#ifndef ossimPlanetUtility_HEADER
+#define ossimPlanetUtility_HEADER
+#include <osg/CoordinateSystemNode>
+#include <osg/Vec3d>
+#include "ossimPlanetExport.h"
+
+class OSSIMPLANET_DLL ossimPlanetUtility
+{
+public:
+ static double getMaxDistance()
+ {
+ return 1.0e10;
+ }
+ static osg::Vec3d normal(const osg::EllipsoidModel& model,
+ double x, double y, double z);
+ static void ellipsoidToXYZ( const osg::EllipsoidModel& model,
+ double latitude, double longitude, double height,
+ double &x, double &y, double &z);
+ static void XYZToEllipsoid( const osg::EllipsoidModel& model,
+ double x, double y, double z,
+ double& latitude, double& longitude, double& height);
+
+ static bool intersectsEllipsoid(const osg::EllipsoidModel& model,
+ osg::Vec3d& intersection,
+ const osg::Vec3d& start,
+ const osg::Vec3d& end);
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetVideoLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetVideoLayer.h
new file mode 100644
index 0000000..fcb1b5d
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetVideoLayer.h
@@ -0,0 +1,61 @@
+#ifndef ossimPlanetVideoLayer_HEADER
+#define ossimPlanetVideoLayer_HEADER
+#include "ossimPlanetLayer.h"
+#include <ossim/base/ossimFilename.h>
+#include <ossimPlanet/ossimPlanetVideoLayerNode.h>
+
+class ossimPlanet;
+class OSSIMPLANET_DLL ossimPlanetVideoLayer : public ossimPlanetLayer
+{
+public:
+ ossimPlanetVideoLayer()
+ {
+ }
+ virtual osg::Object* cloneType() const { return new ossimPlanetVideoLayer(); }
+ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ossimPlanetVideoLayer *>(obj)!=0; }
+ virtual const char* className() const { return "ossimPlanetVideoLayer"; }
+ virtual const char* libraryName() const { return ""; }
+
+ virtual void traverse(osg::NodeVisitor& nv);
+
+ virtual bool add(const ossimFilename& file);
+
+
+ virtual bool addChild( Node *child )
+ {
+ if(dynamic_cast<ossimPlanetVideoLayerNode*>(child))
+ {
+ return ossimPlanetLayer::addChild(child);
+ }
+ return false;
+ }
+ virtual bool insertChild( unsigned int index, Node *child )
+ {
+ if(dynamic_cast<ossimPlanetVideoLayerNode*>(child))
+ {
+ return ossimPlanetLayer::insertChild(index, child);
+ }
+ return false;
+
+ }
+ virtual bool replaceChild( Node *origChild, Node* newChild )
+ {
+ if(dynamic_cast<ossimPlanetVideoLayerNode*>(newChild))
+ {
+ return ossimPlanetLayer::replaceChild(origChild, newChild);
+ }
+ return false;
+ }
+ virtual bool setChild( unsigned int i, Node* node )
+ {
+ if(dynamic_cast<ossimPlanetVideoLayerNode*>(node))
+ {
+ return ossimPlanetLayer::setChild(i, node);
+ }
+ return false;
+ }
+
+
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetVideoLayerNode.h b/ossimPlanet/include/ossimPlanet/ossimPlanetVideoLayerNode.h
new file mode 100644
index 0000000..c01eca7
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetVideoLayerNode.h
@@ -0,0 +1,72 @@
+#ifndef ossimPlanetVideoLayerNode_HEADER
+#define ossimPlanetVideoLayerNode_HEADER
+#include <ossimPlanet/ossimPlanetAnnotationLayerNode.h>
+#include <ossim/base/ossimFilename.h>
+
+class ossimPlanetVideoLayer;
+/**
+ *
+ * I will eventually have this do the drawing and let the derived classes just populate the geometries.
+ * For now, I will put the implementation in ossimPlanetPredatorVideoLayerNode and move implementations out
+ * as we finish and test them.
+ *
+ */
+class OSSIMPLANET_DLL ossimPlanetVideoLayerNode : public ossimPlanetAnnotationLayerNode
+{
+public:
+ enum Status
+ {
+ STATUS_NONE = 0,
+ STATUS_PLAYING,
+ STATUS_PAUSED
+ };
+ enum RenderMode
+ {
+ RENDER_SCREEN = 0,
+ RENDER_BILLBOARD = 1,
+ RENDER_OVERLAY = 2
+ };
+ ossimPlanetVideoLayerNode(ossimPlanetVideoLayer* layer):theLayer(layer){}
+ virtual ~ossimPlanetVideoLayerNode(){}
+ virtual bool open(const ossimFilename& file)=0;
+
+ virtual void pause()=0;
+ virtual void rewind()=0;
+ virtual void play()=0;
+ virtual ossim_float64 duration()const=0;
+ virtual ossimPlanetVideoLayerNode::Status status()const = 0;
+ virtual void setReferenceTime(ossim_float64 reference)=0;
+ virtual ossim_float64 referenceTime()const=0;
+ virtual ossimPlanetVideoLayerNode::RenderMode renderMode()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theVideoLayerNodeMutex);
+ return theRenderMode;
+ }
+ virtual void setRenderMode(ossimPlanetVideoLayerNode::RenderMode mode)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theVideoLayerNodeMutex);
+ theRenderMode = mode;
+ }
+
+ void setVideoLayer(ossimPlanetVideoLayer* layer)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theVideoLayerNodeMutex);
+ theLayer = layer;
+ }
+ ossimPlanetVideoLayer* videoLayer()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theVideoLayerNodeMutex);
+ return theLayer;
+ }
+ const ossimPlanetVideoLayer* videoLayer()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theVideoLayerNodeMutex);
+ return theLayer;
+ }
+
+protected:
+ mutable ossimPlanetReentrantMutex theVideoLayerNodeMutex;
+ ossimPlanetVideoLayer* theLayer;
+ ossimPlanetVideoLayerNode::RenderMode theRenderMode;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetViewMatrixBuilder.h b/ossimPlanet/include/ossimPlanet/ossimPlanetViewMatrixBuilder.h
new file mode 100644
index 0000000..57b036c
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetViewMatrixBuilder.h
@@ -0,0 +1,680 @@
+#ifndef ossimPlanetViewMatrixBuilder_HEADER
+#define ossimPlanetViewMatrixBuilder_HEADER
+#include <osg/Matrix>
+#include <osg/Node>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetPointModel.h>
+#include <ossimPlanet/ossimPlanetLsrSpaceTransform.h>
+#include <osg/ref_ptr>
+
+/**
+ * The view matrix builder serves several purposes. It can be used to allow one to do free form manipulation of the scene
+ * based on position and euler heading pitch roll orientation. Also, one can use the class to "track" another node whether
+ * you are a fixed point looking at a moving object or a moving object looking at another moving object or a moving object
+ * looking at a fixed point or looking from a fixed point to a fixed point. To support all these scenarios we have decomposed
+ * the stages internally to build the matrix into self contained paramters where each can be adjusted by a maniopulator.
+ * Tracking in the true since of the word is really done by the ossimPlanetManipulator which owns a ViewMatrixBuilder and listens
+ * for changes in nodes that either we are looking from or looking to and adjusts the paramters of the view matrix accordingly.
+ *
+ *
+ * Each parameter updates the matrix at it's defined stage. The multiplication or building up the final view matrix is done
+ * in the following steps:
+ * <pre>
+ * Step 1 - Compute a Lsr Matrix with the current "from" Lat lon height position and a composited orientation
+ * created based on the "from" Heading Pitch and Roll and the Relative Heading Pitch and Roll and relative flags.
+ * Step 2 - Apply the From displacement to the current oriented axis. The from displacement will shift the
+ * "from" eye position to a displacement relative to the position and orientation of the matrix from Step 1. Each
+ * X, Y, Z value in the displacement vector is multiplied by the axis of the rotational matrix and added to
+ * the Step 1's origin defined by the from Lat lon height in world X, Y, Z space.
+ * Step 3 - Calculate a look vector at this point based on the Look vector alignment. The default alignment is
+ * to position the look direction along the positive Y-Axis. We will use this vector for other calculations
+ * in later steps.
+ * Step 4 - Displacement along the look axis calculated in Step 3 a "from range" distance.
+ * Step 5 - If there is no "to" information set then we create a lookAt view matrix using OSG's make look at by using the
+ * look vector calculated in Step 3. If there is a look "to" information set then goto Step 8.
+ * Step 6 - If the "to" information is set then first redefine a look vector that looks along the axis to the point you
+ * are looking at.
+ * Step 7 - Now apply 2 displacments. The "ToRange" is a convenient displacement that could be achieved by using just
+ * the z component of the to displacment. The "to range" is added to the Z component of the "to displacement".
+ * the displacement is then applied to the axis created by using the look vector calculated in Step 6 and the makeLookAt
+ * utility supplied to us by OSG. This will create an orientation axis and we display the current displaced eye point
+ * calculated in the from stage along the new axis.
+ * Step 8 - Apply the final Attitude to allow one to look around.
+ * </pre>
+ *
+ * How to use the view matrix builder.
+ *
+ * - Free form manipulation where you are just wanting to move the eye around. the paramters typically used are the
+ * "from Lat lon Height" and the from Heading pitch and roll. The from Realtive flags should be set to ALL and the relative
+ * heading pitch roll and all other values should be zeroed out. The to information should be invalidated and not set.
+ *
+ * - fixed point. you can set the from information to a fixed location and allow yourself to spin around the fixed point
+ * by adjusting the from range and look axis and the from heading pitch and roll. I would default the relative orientation to 0's
+ * and the relative orientation flags to ALL.
+ *
+ * - fixed point to fixed point. There are 2 ways to implement this type of situation. The little bit harder one to setup
+ * is to use it all as a from point with a range displacement. So you could orient the From HPR axis and do a negative
+ * range displacement along the look direction for the from orientation. The easier to control and setup is to treat the point
+ * to point type implementation as a "from to" setting. So we set the from position Lat Lon Height and the point you are looking
+ * at Lat Lon Height. We then set the orientaiton information for the from axis to all 0 and relative to all. This will use the
+ * normal of the local tangent axis at the from position for the calculation of a "make look at". This will also keep the horizon
+ * level.
+ *
+ * - fixed point to a node. Currently we only support orientation and positional lookups for nodes that are or contain a node of
+ * type ossimPlanetPointModel or of type ossimPlanetLsrSpace. We will later add some of OSG's position attitude models. The
+ * view matrix does not auto track but auto tracking is done outside the class (@see ossimPlanetManipulator). Since the node is
+ * the "to" node the orientation information is not used from the passed in node. We only use the transform to get the global
+ * position of the node in Lat Lon Height. The from position is fixed and should use te set routines that do not take a from node.
+ * to keep the horizon pretty much level you can set the "from fixed point" orientation to all 0 for from HPR and from Relative HPR
+ * and make relative flags set to all relative. This will use the normal to the tangent plane as the up axis used in the calculation
+ * of the makeLookAt call.
+ *
+ * - node to fixed point. How the look to the fixed point is oriented will depend on the settings of the relative orientation flags.
+ * the from point is created from the nodes location and then the orientation is grabbed from the node. We currently only support
+ * locating an ossimPlanetLsrSpace somewhere as a child of node and we also can detect ossimPlanetPointModel.
+ * The orientation of the lsr space and the location of the point model is used to populate the from information.
+ * The relative flags used will dtermine how the eye tilts when doing a lookat vector to the fixed point. If you want it to
+ * not allow the horizon to move but stay level then I would do a NOR ORIENTATION FLAG and the relative HPR values are actually
+ * used in the orientation and so giving them the value of all 0 should keep the horizon level.
+ *
+ * - node to node. Node to node is nothing different than the node to fixed point but in the ossimPlanetManipulator it just keeps
+ * tracking the "to" node. The tilting that occurs depends on how you set up the from information orientation and relative
+ * orientation and the relative orientation flags.
+ */
+class OSSIMPLANET_DLL ossimPlanetViewMatrixBuilder : public osg::Referenced
+
+{
+public:
+ class OSSIMPLANET_DLL Visitor : public osg::NodeVisitor
+ {
+ public:
+ Visitor();
+ virtual void apply(osg::Node& node);
+ virtual void reset()
+ {
+ thePointModel = 0;
+ theLsrSpaceTransform = 0;
+ }
+ osg::ref_ptr<ossimPlanetPointModel> thePointModel;
+ osg::ref_ptr<ossimPlanetLsrSpaceTransform> theLsrSpaceTransform;
+ };
+ /**
+ * These are used as flags for defining relative orientation axis for passed in
+ * heading, pitch, and roll.
+ */
+ enum OrientationFlags
+ {
+ NO_ORIENTATION = 0,
+ HEADING = 1,
+ PITCH = 2,
+ ROLL = 4,
+ ALL_ORIENTATION = (HEADING|PITCH|ROLL)
+ };
+
+ /**
+ * Look axis. Once a defined orientation is created you have the option to define a LOOK axis.
+ */
+ enum LookAxis
+ {
+ LOOK_AXIS_X = 0,
+ LOOK_AXIS_NEGATIVE_X,
+ LOOK_AXIS_Y,
+ LOOK_AXIS_NEGATIVE_Y,
+ LOOK_AXIS_Z,
+ LOOK_AXIS_NEGATIVE_Z
+ };
+ /**
+ * Allow one to construct an empty geo ref model. We need it to have this option
+ * For some nodes in a graph that use this will not know about a model until it's added
+ * to a graph.
+ *
+ * @param geoRefModel Pass in an optional geo ref model during construction time. If not
+ * set here you need to set it with the setGeoRefModel before calling
+ * the viewMatrix and inverseViewMatrix methods.
+ */
+ ossimPlanetViewMatrixBuilder(ossimPlanetGeoRefModel* geoRefModel=0);
+
+ ossimPlanetViewMatrixBuilder(const osg::Matrixd& m, ossimPlanetGeoRefModel* geoRefModel);
+ /**
+ * Copy constructor
+ */
+ ossimPlanetViewMatrixBuilder(const ossimPlanetViewMatrixBuilder& src);
+
+ /**
+ * clone method. Will return an allocated copy of this object.
+ */
+ virtual ossimPlanetViewMatrixBuilder* clone(){return new ossimPlanetViewMatrixBuilder(*this);}
+
+ /**
+ * Standard destructor
+ */
+ virtual ~ossimPlanetViewMatrixBuilder();
+
+ /**
+ * Sets the GeoRefModel used for coordinate transformations.
+ *
+ * @param geoRefModel the current model used for coordinate transformations
+ *
+ */
+ void setGeoRefModel(ossimPlanetGeoRefModel* geoRefModel);
+
+ /**
+ * Basic access method.
+ *
+ * @return the stored geo ref model
+ */
+ const ossimPlanetGeoRefModel* geoRefModel()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theModel.get();
+ }
+ ossimPlanetGeoRefModel* geoRefModel()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theModel.get();
+ }
+
+ /**
+ * This method allows you to define a view that tracks a node. You can eather sit
+ * at the node's defined center of mass or displace a distance "range" along line of site and/or 3d vector displacement.
+ * the relative orientation flag defines how the heading pitch roll argument is to be used
+ * to calculate the final orientation. if any flag is set for Heading, Pitch, and/or roll then
+ * that orientation parameter is relative to that orientation defined in the axis of the node. If
+ * any flag is not set then it is relative to the East North Up axis. So if you want a camera to
+ * always say rotate with the heading of that node then you will just set the HEADING flag in
+ * the relativeOrientationFlag.
+ *
+ * @param node This is the node you wish this ViewMatrixBuilder to Lock to.
+ * @param hpr The passed in Heading Pitch and Roll to apply in angular degrees.
+ * @param range The meter distance along the look axis.
+ * @param relativeOrientationFlag Which orientation parameter(s) do you wish to be relative
+ * to the Node's Axes. A value of ALL_ORIENTATION and a hpr
+ * parameter of all 0's will allow you to rotate with the object.
+ */
+ void setLookFromNodeOffset(osg::Node* node,
+ const osg::Vec3d& hpr,
+ double range,
+ int relativeOrientationFlag);
+
+ /**
+ * This allows for a look from displacement. So for instance if you want to
+ * position the camera truly in the cockpit and not the center of mass used for the local
+ * space transform you can do so. Currently this displacment will follow the local point
+ * center of mass relative to the orientation axis of the plane.
+ *
+ * @param displacement This takes a local space displacement in meters and positions along
+ * the orientation of the node or current relative axis the amount to
+ * displace to the new center.
+ */
+ void setLookFromLocalDisplacement(const osg::Vec3d& displacement)
+ {
+ updateFromLocalDisplacement(displacement);
+ }
+
+ /**
+ * This was added to keep a name consistency problem.
+ */
+ void updateFromLocalDisplacement(const osg::Vec3d& displacement);
+
+ void updateFromPositionLlh(const osg::Vec3d& llh)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromNode = 0;
+ theFromPositionLLH = llh;
+ }
+ void updateFromRange(double range)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromRange = range;
+ setComputeViewMatrixFlag(true);
+ }
+ void updateFromRelativeHpr(const osg::Vec3d& hpr)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromRelativeHpr = hpr;
+ setComputeViewMatrixFlag(true);
+ }
+ void updateFromHpr(const osg::Vec3d& hpr)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromHpr = hpr;
+ setComputeViewMatrixFlag(true);
+ }
+ void updateFromRelativeOrientationFlag(int relativeOrientationFlag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromRelativeOrientationFlags = (OrientationFlags)relativeOrientationFlag;
+ setComputeViewMatrixFlag(true);
+ }
+ void updateFromNode(osg::Node* node)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromNode = node;
+ setComputeViewMatrixFlag(true);
+ }
+ /**
+ * @return The current from node.
+ */
+ osg::Node* fromNode()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromNode.get();
+ }
+ const osg::Vec3d& fromLocalDisplacement()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromDisplacement;
+ }
+
+ /**
+ * This is the starting from position in lat lon height form. This does not
+ * include the displacement information or range information.
+ *
+ * @return the from position in lat lon height.
+ */
+ const osg::Vec3d& fromPositionLlh()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromPositionLLH;
+ }
+
+ /**
+ * This is for the relative heading pitch and roll setting done in the set
+ * relative to a Node call. Also, the internal matrix builder will set
+ * the relative positioning if setting using the fixed point method.
+ *
+ * @return the realtive Hpr setting.
+ */
+ const osg::Vec3d& fromRelativeHpr()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromRelativeHpr;
+ }
+
+ /**
+ * @return the current setting for the relative orientation flags.
+ */
+ OrientationFlags fromRelativeOrientationFlags()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromRelativeOrientationFlags;
+ }
+
+ /**
+ * This will give a composited from orientation based on the Relative flags. Internally the source orientation could
+ * be changing each frame and the rleative orientation offsets the source orientation vector based on the orientation flags.
+ * this is a utility function to allow one to call this in a single call.
+ *
+ * @return the composited orientation vector for heading pitch and roll in degrees.
+ */
+ osg::Vec3d computeFromOrientation()const;
+
+ /**
+ * This is the from source orietation vector.
+ *
+ * @return the from Heading pitch ad roll as a vec3d.
+ */
+ const osg::Vec3d& fromHpr()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromHpr;
+ }
+
+ /**
+ * @return the from range value in meters.
+ */
+ double fromRange()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromRange;
+ }
+
+ /**
+ * @return The current from node as a constant value
+ */
+ const osg::Node* fromNode()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theFromNode.get();
+ }
+
+ /**
+ * This method allow you to set fixed point to look from with a defined orientation and
+ * a displacement along the look as defined by the "range" parameter.
+ *
+ * @param llh This is the <lattitude, longitude, height> where the lat and lon are expressed
+ * in angular degrees and the height is in meters.
+ *
+ * @param hpr This is the <Heading, Pitch, Roll> parameters for the orietation axis relative
+ * to the local tangent plane defined by the point llh. The values are in
+ * angular degrees.
+ *
+ * @param range This indicates the displacement from the axis origin along the line of site or look
+ * vector. Negative value displaces backwards from the look and positive displaces
+ * along the direction of the resulting look.
+ */
+ void setLookFrom(const osg::Vec3d& llh,
+ const osg::Vec3d& hpr,
+ double range);
+
+ /**
+ * If a look to node is specified some of the look from parameters are overriden since the orientation
+ * is dictated by the resulting look vector to the "look to" node that is passed in here.
+ *
+ * @param node The node you wish to look to. It will take the node passed in and use it's
+ * center point information to define to help define a look direction as a vector
+ * going from the "from" location to the "to" node.
+ *
+ */
+ void setLookToNode(osg::Node* node);
+
+ /**
+ * This is a method to define a fixed look to point.
+ *
+ * @param llh This is a <lattitude, longitude, height> vector and the lat and lon are in
+ * angular degrees and the height is in meters.
+ */
+ void setLookTo(const osg::Vec3d& llh);
+
+
+ /**
+ * This allows for a look to displacement. This displaces along the look axis the amount along
+ * the x, y, and z. This is applied after the from axis orientation and positioning is performed
+ *
+ * @param displacement This takes a local space displacement in meters and positions along
+ * the orientation of the node or current relative axis the amount to
+ * displace to the new center.
+ */
+ void setLookToLocalDisplacement(const osg::Vec3d& dispalcement);
+
+ /**
+ * This allows one to specify a displacement along the look axis to the point you are looking.
+ * This is applied after the look to local displacement.
+ */
+ void setLookToRange(double range);
+
+ /**
+ * Sets the global range. This is applied in the direction of the view matrix look.
+ *
+ * @param range The range is in meters.
+ */
+ void setRange(double range);
+
+ /**
+ * Returns the range
+ */
+ double range()const;
+ /**
+ * This is the last applied transform and will generate the final orientation matrix for
+ * the view. This is done after a look from and to calculations and allows one to move the
+ * head around.
+ *
+ * @param hpr This is the relative heading pitch and roll about the final orientation axis.
+ *
+ */
+ void setAttitudeHpr(const osg::Vec3d& hpr)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theAttitudeHpr = hpr;
+ setComputeViewMatrixFlag(true);
+
+ }
+
+ /**
+ * @return The attitude of the final look position. This is the Heading pitch and roll
+ * relative to the final orientation axes.
+ */
+ const osg::Vec3d& attitudeHpr()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theAttitudeHpr;
+ }
+
+ /**
+ * @return The to information set flag. A value of true specifies that
+ * the look to information was set
+ */
+ bool toInformationSetFlag()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theToInformationSetFlag;
+ }
+ /**
+ * @return The current to node.
+ */
+ osg::Node* toNode()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theToNode.get();
+ }
+
+ /**
+ * @return The current to node as a constant value.
+ */
+ const osg::Node* toNode()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theToNode.get();
+ }
+
+ /**
+ * This should only be called if a look to was set.
+ *
+ * @return the Look to position lat lon height as a Vec3d.
+ */
+ const osg::Vec3d& toPositionLlh()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theToPositionLLH;
+ }
+
+ /**
+ * This is a displacement along the current Rotational axis.
+ */
+ const osg::Vec3d& toDisplacement()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theToDisplacement;
+ }
+
+ /**
+ */
+ double toRange()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theToRange;
+ }
+
+ /**
+ * This allows one to change the look axis you wish to look down.
+ * After the orientation is applied you can set the look axis you wish
+ * to use. This is not used if you are looking at another node or a fixed point
+ * for the look direction is already known. This is used only when you are in a
+ * from location only and will allow you to swap between axis to look down. So you
+ * can easily look up, down, left, right, ... etc
+ *
+ * @param LookAxis The axis to look down, see LookAxis enumeration for possible
+ * values.
+ */
+ void setLookAxis(LookAxis axis)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theLookAxis = axis;
+ setComputeViewMatrixFlag(true);
+ }
+ /**
+ * @return The current look axis.
+ */
+ LookAxis lookAxis()const
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theLookAxis;
+ }
+
+ /**
+ * This matrix you can think of as placing objects out into the scene.
+ * Basically a local to world transform.
+ * @return the composited view Matrix as defined by the look to and from parameter settings.
+ */
+ const osg::Matrixd& viewMatrix()const;
+
+ /**
+ * This takes world coordinates and puts it into this local orientation. This is typically
+ * used to set a Camera Matrix. Call this to set a osg::Camera matrix or to set a manipulators
+ * setByMatrix.
+ *
+ * @return The inverse of the view matrix.
+ */
+ const osg::Matrixd& inverseViewMatrix()const;
+
+ /**
+ * Returns true or false if there is enough information to compute a matrix. We will need the
+ * geoRefModel for coodrinate transformations and at least the From point information
+ * needs to be set.
+ *
+ * @return true if a call to viewMatrix would be valid or false otherwise.
+ */
+ bool isValid()const{return (theModel.valid()&&theFromInformationSetFlag);}
+
+ void setFromInformationSetFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromInformationSetFlag = flag;
+ }
+ void setToInformationSetFlag(bool flag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theToInformationSetFlag = flag;
+ }
+
+ /**
+ * @see setParametersByMatrix.
+ *
+ * This just wraps the call to the setParamtersByMatrix to invert the
+ * passed in matrix.
+ *
+ * @param m Inverted matrix.
+ */
+ void setParametersByInverseMatrix(const osg::Matrixd& m)
+ {
+ osg::Matrixd newM(osg::Matrixd::inverse(m));
+ setParametersByMatrix(newM);
+ }
+
+ /**
+ *
+ * Allows one to extract the absolute position and orientation of the composited
+ * view matrix. We still have a problem if the viewMatrix has a roll component influencing
+ * the solution. We don't get an exact inverse.
+ *
+ */
+ virtual bool extractCompositedLlhHprParameters(osg::Vec3d& llh,
+ osg::Vec3d& hpr)const;
+
+ /**
+ * This will take a matrix and flatten the parameters of the ViewMatrixBuilder to be purely a from
+ * unlocked type ViewMatrixBuilder. It will take the matrix passed in and extract out the eye position
+ * and orientation hpr. All other values such as range any to values will be zeroed out. All nodes
+ * that we were locked to will be nulled out.
+ *
+ * @param m The matrix to use to convert the ViewMatrixBuilder to.
+ *
+ */
+ virtual void setParametersByMatrix(const osg::Matrixd& m);
+
+ /**
+ * Converts the paramters to a from only. If the range is to be preserved by setting
+ * the flatten range flag to false and there is a to point that we are looking at then
+ * it will preserve the distance in the from range and setup a from only paramter ViewMAtrixBuilder.
+ *
+ * When using this call the Attitude orientation is not taken into account since this is used as a final
+ * displacement. So, the Attitude values are preserved but are removed from the orientation calculation
+ * for the new from HPR.
+ *
+ */
+ virtual void convertToAFromViewMatrix(bool flattenRangeFlag = false);
+ void invalidateFrom()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromInformationSetFlag = false;
+ theFromNode = 0;
+ }
+ void invalidateTo()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theToInformationSetFlag = false;
+ theToNode = 0;
+ }
+ void invalidate()
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromInformationSetFlag = false;
+ theFromNode = 0;
+ theToNode = 0;
+ }
+protected:
+ /**
+ * Sets an internal flag to say that the view matrix needs to be recomputed.
+ *
+ * @param flag a true value will have the next call to viewMatrix or viewInverseMatrix
+ * recalculate the matrices.
+ */
+ void setComputeViewMatrixFlag(bool flag)
+ {
+ theComputeViewMatrixFlag = flag;
+ }
+
+ /**
+ * Returns the view matrix flag
+ */
+ bool computeViewMatrixFlag()const
+ {
+ return theComputeViewMatrixFlag;
+ }
+
+ /**
+ * Recomputes the view matrix based on all the from and to paraemters.
+ */
+ virtual void computeMatrices()const;
+
+ /**
+ * Thread sync mutex for multiple threads hitting the object.
+ */
+ mutable OpenThreads::ReentrantMutex thePropertyMutex;
+
+ /**
+ * A referenced pointer to the current Model in planet.
+ */
+ osg::ref_ptr<ossimPlanetGeoRefModel> theModel;
+
+ /**
+ * The look axis for defining whihc axis to look down when in
+ * view mode only.
+ */
+ LookAxis theLookAxis;
+
+ bool theFromInformationSetFlag;
+ osg::ref_ptr<osg::Node> theFromNode;
+ osg::Vec3d theFromPositionLLH;
+ osg::Vec3d theFromRelativeHpr;
+ OrientationFlags theFromRelativeOrientationFlags;
+ osg::Vec3d theFromHpr;
+ double theFromRange;
+ osg::Vec3d theFromDisplacement;
+
+ bool theToInformationSetFlag;
+ osg::ref_ptr<osg::Node> theToNode;
+ osg::Vec3d theToPositionLLH;
+ osg::Vec3d theToDisplacement;
+ double theToRange;
+
+ osg::Vec3d theAttitudeHpr;
+ double theRange;
+ mutable osg::Matrix theViewMatrix;
+ mutable osg::Matrix theInverseViewMatrix;
+ mutable bool theComputeViewMatrixFlag;
+};
+
+#endif // OSSIMPLANETVIEWMATRIXBUILDER_H_
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetViewer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetViewer.h
new file mode 100644
index 0000000..04e2f27
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetViewer.h
@@ -0,0 +1,487 @@
+#ifndef ossimPlanetViewer_HEADER
+#define ossimPlanetViewer_HEADER
+#include <osgDB/DatabasePager>
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetCallback.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <ossimPlanet/ossimPlanetNode.h>
+#include <osgViewer/Viewer>
+//#include <osgViewer/Renderer>
+#include <ossimPlanet/ossimPlanet.h>
+#include <osg/ref_ptr>
+#include <osg/Node>
+#include <ossimPlanet/ossimPlanetNode.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <osgUtil/LineSegmentIntersector>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetAnnotationLayer.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <ossimPlanet/ossimPlanetEphemeris.h>
+#include <OpenThreads/Mutex>
+
+class ossimPlanetManipulator;
+class ossimPlanetViewer;
+class OSSIMPLANET_DLL ossimPlanetViewerCallback : public ossimPlanetCallback
+{
+public:
+ virtual void viewChanged(ossimPlanetViewer* /*viewer*/){}
+};
+
+/**
+ *
+ * ossimPlanetViewer will serve as a higher level interface to most of the ossimPlanet's inner workings. During the update phase it will determine if
+ * the scnee graph is in a static state ad will notify the user through a virtual method callback. At the time of this documentation we have not written then API
+ * to auto setup the planet node. This is an example to setup the planet node and then set it to the Viewer. Note, this code will eventually be moved into
+ * a single setup routine on ossimPlanetViewer.
+ *
+ * <pre>
+ * viwer->addEventHandler( new osgGA::StateSetManipulator(theCanvas->getCamera()->getOrCreateStateSet()));
+ * viewer->addEventHandler(new osgViewer::StatsHandler());
+ * viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
+ * osg::ref_ptr<ossimPlanet> planet = new ossimPlanet;
+ * planet->setupDefaults();
+ * planet->land()->setCurrentFragementShaderType(ossimPlanetShaderProgramSetup::NO_SHADER);
+ * viewer->setSceneData(planet.get());
+ * viewer->addImageTexture("/data/earth/earth.jpg");
+ *
+ * viewer->setCameraManipulator(new ossimPlanetManipulator());
+ * </pre>
+ *
+ * this example sets some GUI action handlers supported by OSG. We allocate a planet and then call planets setupDefaults().
+ * I then set the scene to the viewer and then add an image to the earth. The last thing we did was setup the manipulator that will
+ * manipulate the eye matrix of OSG. We have our own manipulator called ossimPlanetManipulator.
+ */
+class OSSIMPLANET_DLL ossimPlanetViewer : public osgViewer::Viewer,
+ public ossimPlanetCallbackListInterface<ossimPlanetViewerCallback>,
+ public ossimPlanetActionReceiver
+
+{
+public:
+ class InitializePointersVisitor;
+ friend class InitializePointersVisitor;
+
+ /**
+ * PickObject is used to hold the node path information when picking objects
+ * in the scene. For each object intersected a complete node path is stored.
+ * A higher level api is placed on PickObject to give access to the most common attributes.
+ *
+ * <pre>
+ * Exmaple usage:
+ * assume we have a pointer to ossimPlanetViewer called viewer and we have variables wx and wy at the window location
+ * to pick.
+ *
+ * std::vector<osg::ref_ptr<PickObject> > pickResult,
+ * viewer->pickAtWindowCoordinate(pickResult, wx,wy);
+ *
+ * if(pickResult.size() > 0)
+ * {
+ * // now access the Picked objects.
+ * }
+ * </pre>
+ */
+ class OSSIMPLANET_DLL PickObject : public osg::Referenced
+ {
+ public:
+ typedef std::vector<osg::ref_ptr<osg::Node> > Path;
+ /**
+ * Used by the intersection routines to construct all the default values for the object.
+ */
+ PickObject(const osg::NodePath& nodePath,
+ const osg::Vec3d& localPoint,
+ const osg::Vec3d& worldPoint,
+ const osg::Vec3d& llh)
+ :theNodePath(nodePath.begin(), nodePath.end()),
+ theLocalPoint(localPoint),
+ theWorldPoint(worldPoint),
+ theLatLonHeightPoint(llh)
+ {}
+
+ /**
+ * @return the objects local point
+ */
+ const osg::Vec3d& localPoint()const{return theLocalPoint;}
+
+ /**
+ * @param value local point
+ */
+ void setLocalPoint(osg::Vec3d& value){theLocalPoint = value;}
+
+ /**
+ * This will return the objects world point. Note this is in the space that the x,y,z coordinates are in
+ * So if normalized ellipsoidalmode then values are in normalized ellipsoid.
+ */
+ const osg::Vec3d& worldPoint()const{return theWorldPoint;}
+
+ /**
+ * @param value world point
+ */
+ void setWorldPoint(osg::Vec3d& value){theWorldPoint = value;}
+
+ /**
+ * This returns the lat, lon, height in the mode of the model. By default the model uses wgs84 horizontal
+ * datum. The height is currently not shifted relative to any geoid so it is an ellipsoidal height at this point.
+ */
+ const osg::Vec3d& llh()const{return theLatLonHeightPoint;}
+ void setllh(const osg::Vec3d& value){theLatLonHeightPoint = value;}
+
+ /**
+ * Will search the node path and return a pointer to the ossimPlanetNode that is first encountered. If
+ * no ossimPlanetNode is encountered then null is returned
+ */
+ ossimPlanetNode* firstPlanetNode();
+
+ protected:
+ ossimPlanetViewer::PickObject::Path theNodePath;
+ osg::Vec3d theLocalPoint;
+ osg::Vec3d theWorldPoint;
+ osg::Vec3d theLatLonHeightPoint;
+ };
+
+ /**
+ * The NodeListener is used internally to ossimPlanetViewer to listen to things in the graph so it can effectively
+ * determine if a graph is at a static state.
+ */
+ class OSSIMPLANET_DLL NodeListener: public ossimPlanetNodeCallback
+ {
+ public:
+ NodeListener(ossimPlanetViewer* viewer)
+ :theViewer(viewer)
+ {
+
+ }
+ virtual void nodeAdded(osg::Node* /*node*/);
+ virtual void nodeRemoved(osg::Node* /*node*/);
+ virtual void needsRedraw(ossimPlanetNode* node);
+
+ protected:
+ ossimPlanetViewer* theViewer;
+ };
+ friend class NodeListener;
+
+
+ /**
+ * Shorthand typedef of a list of Pick objects.
+ */
+ typedef std::vector<osg::ref_ptr<PickObject> > PickList;
+ /**
+ * Shorthand typedef of a PlanetNode list.
+ */
+ typedef std::vector<osg::ref_ptr<ossimPlanetNode> > PlanetNodeList;
+ /**
+ * Shorthand typedef to hold a list of hud nodes.
+ */
+ typedef std::vector<osg::ref_ptr<osg::Node> > HudList;
+
+ /**
+ * constructor for ossimPlanetViewer. Initializing internal pointers and sets up the Update visitor
+ * that will be used to determine if the graph needs refreshing.
+ */
+ ossimPlanetViewer();
+ /**
+ * Constructs with arguments. Note this is bridged for osgViewer since ossimPlanetViewer derives from it.
+ */
+ ossimPlanetViewer(osg::ArgumentParser& arguments);
+
+ /**
+ * Copy constructor. Currently ossimPlanetViewer ignores this and passes on up to osgViewer.
+ */
+ ossimPlanetViewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ /**
+ * destorys and allocated data and removes callbacks form any internal nodes in the scene graph that ossim
+ * PlanetViewer was listneeing to
+ */
+ virtual ~ossimPlanetViewer();
+
+ /**
+ *
+ * Note only 1 ossimPlanet should exist in a graph. ossimPlanetViewer searches for the ossimPlanet node and
+ * will unset any previous setup pointers to the newly found ossimPlanet object.
+ *
+ */
+ virtual void setSceneData(osg::Node* node);
+
+ void initializeIncrementalCompile();
+
+ /**
+ * Gives acdcess to any allocated ossimPlanet object found in the setSceneData call.
+ */
+ ossimPlanet* planet();
+
+ /**
+ * Gives acdcess to any allocated ossimPlanet object found in the setSceneData call.
+ */
+ const ossimPlanet* planet()const;
+
+ /**
+ * Override this to mark the start of the framing
+ */
+ virtual void advance(double simulationTime=USE_REFERENCE_TIME);
+
+ /**
+ * virtual method override form base class. We check the ossimPlanetUpdte visitor to see if any need refresh flags were found
+ * in the scnee graph.
+ */
+ virtual void updateTraversal();
+
+ virtual void eventTraversal();
+ /**
+ * Utility method to give you access to the continuous equation model used for the ellipsoidal tesselation.
+ */
+ const ossimPlanetGeoRefModel* model()const;
+ ossimPlanetGeoRefModel* model();
+
+ /**
+ * This will be reserved for executing messages routed to the view object. No implementation yet for this method.
+ */
+ virtual void execute(const ossimPlanetAction& action);
+
+ /**
+ * This will return the eye origin and a normalized ray direction given a window coordinate. This is unnormalized
+ * window coordinate and assumes Y is up. So if you are in a GUI where Y is down (left handed) then you must flip and make Y up
+ * using some formula like: height() - Y.
+ */
+ virtual bool makeRayAtWindowCoordinate(osg::Vec3d& origin,
+ osg::Vec3d& ray,
+ double wx, double wy);
+
+
+ /**
+ * This is a utility method for picking objects. The passed in wx and wy are in unnormalized window coordinates. Assumed that
+ * the passed in coordinates are right handed where Y is up. So if you are in a GUI where Y is down (left haded) then you must flip and make Y up
+ * using some formula like: height() - Y.
+ */
+ virtual bool pickAtWindowCoordinate(PickList& result,
+ double wx, double wy,
+ osg::Node::NodeMask traversalMask = 0xffffffff);
+ /**
+ * This is a utility method for picking objects. The passed in wx and wy are in unnormalized window coordinates. Assumed that
+ * the passed in coordinates are right handed where Y is up. So if you are in a GUI where Y is down (left haded) then you must flip and make Y up
+ * using some formula like: height() - Y.
+ */
+ virtual bool getLatLonHeightAtWindowCoordinate(osg::Vec3d& llh,
+ double wx, double wy,
+ osg::Node::NodeMask traversalMask=0xffffffff);
+
+ /**
+ * will add and manage the hud.
+ */
+// bool AddHudOverlay(osg::ref_ptr<osg::Node> hudNode);
+// ossim_uint32 getNumberOfHudOverlays()const;
+
+ /**
+ * This will take the passed in anotation node and add it to the annotation layer in planet.
+ *
+ * @param annotation Annotation node to add to planet.
+ */
+ bool addAnnotation(osg::ref_ptr<ossimPlanetAnnotationLayerNode> annotation);
+
+ /**
+ *
+ * This will take a texture layer and add it to the top of the reference layer.
+ *
+ * @param imageLayer Texture layer to be added.
+ * @return true if the layer was added successfully.
+ *
+ */
+ bool addImageTexture(osg::ref_ptr<ossimPlanetTextureLayer> imageTexture);
+
+ /**
+ * Will open all entries and return as a root image layer. If this image file only contains a single
+ * image then that layer is returned. If multipl images are found then it will open each image and
+ * create a Layer group and return the images all grouped together.
+ *
+ * @param file The file to open adn add to the graph
+ *
+ * @return the Root layer node.
+ */
+ osg::ref_ptr<ossimPlanetTextureLayer> addImageTexture(const ossimString& file);
+
+ /**
+ * Allows one to add elevation database.
+ *
+ * @param the elevation database to add.
+ * @param sortFlag will specify if you want to re-sort the database based on resolution.
+ *
+ */
+ bool addElevation(osg::ref_ptr<ossimPlanetElevationDatabase> database, bool sortFlag=false);
+
+ /**
+ * Allows one to add a kml resource to the kml layer
+ *
+ **/
+ void addKml(const ossimFilename& file);
+
+ /**
+ * This will take the current active camera and calculate ossimPlanetLookAt representations
+ * for the eye and the lookat point.
+ *
+ * You should not have to call this for it is already called after each update traversal.
+ */
+ void computeCurrentCameraInfo();
+
+ /**
+ * Utility to search the scene graph for objects of type ossimPlanetNode that are in the scene graph and has
+ * the passed in id
+ */
+ void findNodesWithId(ossimPlanetViewer::PlanetNodeList& nodeList,
+ const ossimString& id);
+ /**
+ * Utility to search the scene graph for objects of type ossimPlanetNode that are in the scene graph and has
+ * the passed in id
+ */
+ osg::ref_ptr<ossimPlanetNode> findFirstNodeWithId(const ossimString& id);
+
+
+ /**
+ * Lookat object is maintained at any view change within the ossimPlanetViewer. You can at anytime obtain
+ * the current lookat.
+ */
+ const ossimPlanetLookAt* currentLookAt()const{return theCurrentLookAt.get();}
+
+ /**
+ * Camera object is stored in the format of a lookat object where the range value is 0. The Eye position and oritentation is
+ * a special case of a look at object. This is maintained at any view change automatically by ossimPlanetViewer
+ * and can be queried at any time.
+ *
+ * @return Eye position and orientation in the form of a LookAt object.
+ */
+ const ossimPlanetLookAt* currentCamera()const{return theCurrentCamera.get();}
+
+ /**
+ * This currently may change. We are exposing some control of how fast objects are added to the graph
+ * at runtime. This in particular is an interface added for ossimPlanetTerrain engine. It will pass
+ * the value on to the terrain and will indicate how many tile request operation to apply to the graph
+ * per frame. So the higher the number the more requests that are finalized will be applied to the graph.
+ *
+ * Note: Requests can be a split, update a mesh, or update a texture. Each of these adds content to the
+ * scene and how fast it's added can be controlled by this variable.
+ */
+ void setTerrainMaxNumberOfOperationsToApplyToGraphPerFrame(ossim_uint32 value);
+
+ ossimPlanetManipulator* planetManipulator();
+ ossimPlanetTerrain* terrainLayer();
+ ossimPlanetAnnotationLayer* annotationLayer();
+ ossimPlanetKmlLayer* kmlLayer();
+ void addEphemeris(ossim_uint32 memberBitMask);
+ void removeEphemeris();
+ ossimPlanetEphemeris* ephemeris();
+
+ /**
+ * We will bridge the GUI action adapter so these values can be poled
+ */
+ virtual void requestRedraw();
+ virtual void requestContinuousUpdate(bool needed=true);
+ virtual void requestWarpPointer(float x,float y);
+
+
+ /**
+ * This is an atomic operation so if another request redraw comes in while you are querying
+ * they will be in synch. Instead of doing a separate query of the redraw flag and then
+ * a set on it for a new request could come in while in between those 2 calls and therefore you will
+ * miss a frame.
+ */
+ bool getAndSetRedrawFlag(bool newValue);
+ bool getRedrawFlag();
+ void setRedrawFlag(bool flag);
+ bool redrawFlag()const;
+ void setContinuousUpdateFlag(bool flag);
+ bool continuousUpdateFlag()const;
+ bool warpPointerFlag()const;
+ void getWarpPoints(float& x, float& y)const;
+
+ /**
+ * All code contained in here was copied from OSG. We will be adding fudge factor shifts
+ * for close to earth intersections.
+ *
+ * Compute intersections between a ray through the specified master cameras window/eye coords and a specified node.
+ * Note, when a master cameras has slaves and no viewport itself its coordinate frame will be in clip space i.e. -1,-1 to 1,1,
+ * while if its has a viewport the coordintates will be relative to its viewport dimensions.
+ * Mouse events handled by the view will automatically be attached into the master camera window/clip coords so can be passed
+ * directly on to the computeIntersections method. */
+ bool computeIntersections(float x,
+ float y,
+ osgUtil::LineSegmentIntersector::Intersections& intersections,
+ osg::Node::NodeMask traversalMask = 0xffffffff);
+
+ /**
+ * All code contained in here was copied from OSG. We will be adding fudge factor shifts
+ * for close to earth intersections.
+ *
+ * Compute intersections between a ray through the specified master cameras
+ * window/eye coords and a specified nodePath's subgraph.
+ **/
+ bool computeIntersections(float x,
+ float y,
+ const osg::NodePath& nodePath,
+ osgUtil::LineSegmentIntersector::Intersections& intersections,
+ osg::Node::NodeMask traversalMask = 0xffffffff);
+ /**
+ * This will return the eye origin and a normalized ray direction given a window coordinate. This is unnormalized
+ * window coordinate and assumes Y is up. So if you are in a GUI where Y is down (left haded) then you must flip and make Y up
+ * using some formula like: height() - Y.
+ */
+ virtual bool makeRayAtWindowCoordinate(osg::Vec3d& origin,
+ osg::Vec3d& ray,
+ osg::Camera* camera,
+ double wx, double wy);
+
+ void setIntersectWithMasterIfNotWithinAnyViewFlag(bool flag)
+ {
+ theIntersectWithMasterIfNotWithinAnyViewFlag = flag;
+ }
+ bool intersectWithMasterIfNotWithinAnyViewFlag()const
+ {
+ return theIntersectWithMasterIfNotWithinAnyViewFlag;
+ }
+ void setCalculateNearFarRatioFlag(bool flag)
+ {
+ theCalculateNearFarRatioFlag = flag;
+ }
+ bool calculateNearFarRatioFlag()const
+ {
+ return theCalculateNearFarRatioFlag;
+ }
+protected:
+ friend class DrawCallback;
+ const osg::Camera* forceAdjustToMasterCamera(float x, float y, float& local_x, float& local_y) const;
+
+ void init();
+ void notifyViewChanged();
+
+ HudList theHudOverlayList;
+ osg::ref_ptr<NodeListener> theCallback;
+ osg::ref_ptr<ossimPlanet> thePlanet;
+ osg::ref_ptr<ossimPlanetUpdateVisitor> theUpdateVisitor;
+
+ osg::Matrixd theCurrentViewMatrix;
+ osg::Matrixd theCurrentViewMatrixInverse;
+ osg::ref_ptr<ossimPlanetLookAt> theCurrentCamera;
+ osg::ref_ptr<ossimPlanetLookAt> theCurrentLookAt;
+ osg::ref_ptr<ossimPlanetAnnotationLayer> theAnnotationLayer;
+ osg::ref_ptr<ossimPlanetKmlLayer> theKmlLayer;
+ osg::ref_ptr<ossimPlanetLayer> theTerrainLayer;
+ osg::ref_ptr<ossimPlanetEphemeris> theEphemerisLayer;
+ osg::ref_ptr<osg::Camera> theEphemerisCamera;
+ osg::ref_ptr<osg::Node> theEphemerisRoot;
+
+ osg::ref_ptr<osg::Group> theRootNode;
+ osg::ref_ptr<osg::Light> theSavedLight;
+ osg::Timer_t theFrameStartTimeStamp;
+ /*** These are Gui Action adapter bridge ****/
+ mutable OpenThreads::Mutex theActionAdapterMutex;
+ bool theContinousUpdateFlag;
+ bool theRedrawFlag;
+ bool theWarpPointerFlag;
+ float theWarpX, theWarpY;
+ /*** Done with GUI Action adapter bridge ****/
+
+ bool theIntersectWithMasterIfNotWithinAnyViewFlag;
+ bool theCalculateNearFarRatioFlag;
+
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetVisitors.h b/ossimPlanet/include/ossimPlanet/ossimPlanetVisitors.h
new file mode 100644
index 0000000..998d4b9
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetVisitors.h
@@ -0,0 +1,140 @@
+#ifndef ossimPlanetVisitors_HEADER
+#define ossimPlanetVisitors_HEADER
+#include <ossimPlanet/ossimPlanetExport.h>
+#include <osg/Texture>
+#include <osg/Texture2D>
+#include <osg/StateSet>
+#include <osg/Node>
+#include <iostream>
+#include <osg/NodeVisitor>
+#include <ossim/base/ossimString.h>
+#include <osgUtil/UpdateVisitor>
+
+class OSSIMPLANET_DLL ossimSetNonPowerOfTwoTextureVisitor : public osg::NodeVisitor
+{
+public:
+ ossimSetNonPowerOfTwoTextureVisitor()
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+ {
+ theResizePowerOfTwoHint = false;
+ theMinFilterMode = osg::Texture2D::LINEAR;
+ theMagFilterMode = osg::Texture2D::LINEAR;
+ theSWrapMode = osg::Texture2D::CLAMP_TO_EDGE;
+ theTWrapMode = osg::Texture2D::CLAMP_TO_EDGE;
+ theRWrapMode = osg::Texture2D::CLAMP_TO_EDGE;
+ theDataVariance = osg::Object::STATIC;
+ }
+ virtual void apply(osg::Node& node)
+ {
+ osg::StateSet* set = node.getStateSet();
+ if(set)
+ {
+ osg::Texture* texture = dynamic_cast<osg::Texture*>(set->getTextureAttribute(0,
+ osg::StateAttribute::TEXTURE));
+ if(texture)
+ {
+/* std::cout << GL_CLAMP <<", " << GL_CLAMP_TO_EDGE <<", " << GL_CLAMP_TO_BORDER_ARB << ", " << GL_REPEAT << "\n"; */
+/* std::cout <<"<" << texture->getWrap(osg::Texture2D::WRAP_S) <<", " */
+/* <<texture->getWrap(osg::Texture2D::WRAP_T) << ">\n"; */
+ texture->setFilter(osg::Texture::MIN_FILTER, theMinFilterMode);
+ texture->setFilter(osg::Texture::MAG_FILTER, theMagFilterMode);
+ texture->setWrap(osg::Texture2D::WRAP_S, theSWrapMode);
+ texture->setWrap(osg::Texture2D::WRAP_T, theTWrapMode);
+ texture->setWrap(osg::Texture2D::WRAP_R, theRWrapMode);
+ texture->setDataVariance(theDataVariance);
+ texture->setResizeNonPowerOfTwoHint(theResizePowerOfTwoHint);
+ }
+ }
+ traverse(node);
+ }
+protected:
+ bool theResizePowerOfTwoHint;
+ osg::Texture::FilterMode theMinFilterMode;
+ osg::Texture::FilterMode theMagFilterMode;
+ osg::Texture::WrapMode theSWrapMode;
+ osg::Texture::WrapMode theTWrapMode;
+ osg::Texture::WrapMode theRWrapMode;
+ osg::Object::DataVariance theDataVariance;
+};
+
+class OSSIMPLANET_DLL ossimPlanetLayerNameIdSearchVisitor : public osg::NodeVisitor
+{
+public:
+ ossimPlanetLayerNameIdSearchVisitor()
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+ {
+ }
+ ossimPlanetLayerNameIdSearchVisitor(const ossimString& name, const ossimString& id)
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ theName(name),
+ theId(id)
+ {
+ }
+ void setName(const ossimString& value)
+ {
+ theName = value;
+ }
+ const ossimString& name()const
+ {
+ return theName;
+ }
+ void setId(const ossimString& value)
+ {
+ theId = value;
+ }
+ const ossimString& id()const
+ {
+ return theId;
+ }
+ osg::ref_ptr<osg::Node> node()
+ {
+ return theNode.get();
+ }
+ const osg::ref_ptr<osg::Node> node()const
+ {
+ return theNode.get();
+ }
+ virtual void apply(osg::Node& node);
+protected:
+ ossimString theName;
+ ossimString theId;
+ osg::ref_ptr<osg::Node> theNode;
+};
+
+class OSSIMPLANET_DLL ossimPlanetTraverseCallback : public osg::NodeCallback
+{
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ if(node)
+ {
+ node->traverse(*nv);
+ }
+ }
+};
+
+
+/**
+ * Used to determine if a node in the graph needs refreshing. It will query the refresh flag while its
+ * going through the update phase and set an internal flag. Note, ossimPlanetViewer's updateTraversal
+ * method override uses this information to help determine if it's in a static state
+ */
+class OSSIMPLANET_DLL ossimPlanetUpdateVisitor : public osgUtil::UpdateVisitor
+{
+public:
+ ossimPlanetUpdateVisitor();
+ /**
+ * Virtual method override that calls the base implementation but also sets/clears the RedrawFlag
+ * for next traversal
+ */
+ virtual void reset();
+
+ /**
+ * @return the value of the redraw flag. True means we need to redraw
+ */
+ bool redrawFlag()const;
+protected:
+ virtual void apply(osg::Node& node);
+ virtual void apply(osg::Group& node);
+ bool theRedrawFlag;
+};
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetWmsClient.h b/ossimPlanet/include/ossimPlanet/ossimPlanetWmsClient.h
new file mode 100644
index 0000000..e3bdbe2
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetWmsClient.h
@@ -0,0 +1,99 @@
+#ifndef OSSIMPLANET_WITHOUT_WMS
+#ifndef ossimPlanetWmsClient_HEADER
+#define ossimPlanetWmsClient_HEADER
+#include <vector>
+#include <string>
+#include "ossimPlanetExport.h"
+#include <ossim/base/ossimFilename.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/base/ossimConstants.h>
+#include <wms/wmsClient.h>
+#include <wms/wmsRefPtr.h>
+#include <osg/ref_ptr>
+#include <osg/Referenced>
+#include <ossimPlanet/ossimPlanetOssimImage.h>
+
+class wmsClient;
+class ossimPlanetImage;
+namespace osg
+{
+ class Image;
+}
+
+class OSSIMPLANET_DLL ossimPlanetWmsClient : public osg::Referenced
+{
+ public:
+ ossimPlanetWmsClient(const std::string& server=std::string(""),
+ const std::string& path=std::string(""));
+ ossimPlanetWmsClient(const ossimPlanetWmsClient& src);
+
+ virtual ~ossimPlanetWmsClient();
+
+ void setServer(const std::string& server);
+ void setPath(const std::string& path);
+
+ virtual osg::ref_ptr<ossimPlanetImage> createImage(ossim_uint32 width,
+ ossim_uint32 height,
+ const double& minLat,
+ const double& minLon,
+ const double& maxLat,
+ const double& maxLon,
+ const std::string& filename = std::string(""));
+
+ virtual osg::ref_ptr<ossimPlanetImage> readLocalImage(const std::string& filename)const;
+
+ void setImageType(const std::string& imageType);
+ std::string getImageType()const;
+ std::string getServer()const;
+ std::string getPath()const;
+ void setVersion(const ossimString& version);
+ void setAdditionalParameters(const ossimString& additionalParameters);
+ void setTransparentFlag(bool flag);
+ void setBackgroundColor(const std::string& color);
+ void setProxyHost(const std::string& host)
+ {
+ theWmsClient->setProxyHost(host);
+ }
+ void setProxyPort(const std::string& port)
+ {
+ theWmsClient->setProxyPort(port);
+ }
+ void setProxyUser(const std::string& userName)
+ {
+ theWmsClient->setProxyUser(userName);
+ }
+ void setProxyPassword(const std::string& password)
+ {
+ theWmsClient->setProxyPassword(password);
+ }
+ const std::string& proxyHost()const
+ {
+ return theWmsClient->proxyHost();
+ }
+ const std::string& proxyPort()const
+ {
+ return theWmsClient->proxyPort();
+ }
+ const std::string& proxyUser()const
+ {
+ return theWmsClient->proxyUser();
+ }
+ const std::string& proxyPassword()const
+ {
+ return theWmsClient->proxyPassword();
+ }
+protected:
+ wmsRefPtr<wmsClient> theWmsClient;
+ std::string theServer;
+ std::string thePath;
+ std::string theImageFormats;
+ std::string theImageType;
+ std::string theVersion;
+ std::string theAdditionalParameters;
+ std::string theBackgroundColor;
+ bool theTransparentFlag;
+ osg::ref_ptr<ossimPlanetOssimImage> theImageReader;
+};
+
+#endif
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetWmsImageLayer.h b/ossimPlanet/include/ossimPlanet/ossimPlanetWmsImageLayer.h
new file mode 100644
index 0000000..9dc80a8
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetWmsImageLayer.h
@@ -0,0 +1,128 @@
+#ifndef ossimPlanetWmsImageLayer_HEADER
+#define ossimPlanetWmsImageLayer_HEADER
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossimPlanet/ossimPlanetWmsClient.h>
+class OSSIMPLANET_DLL ossimPlanetWmsImageLayer : public ossimPlanetTextureLayer
+{
+public:
+ ossimPlanetWmsImageLayer();
+ ossimPlanetWmsImageLayer(const ossimPlanetWmsImageLayer& src);
+ virtual ossimPlanetTextureLayer* dup()const;
+ virtual ossimPlanetTextureLayer* dupType()const;
+ virtual ossimString getClassName()const;
+ virtual ossimPlanetTextureLayerStateCode updateExtents();
+ virtual void updateStats()const;
+ virtual void resetStats()const;
+
+ virtual bool hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid);
+
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& theGrid,
+ ossim_int32 padding=0);
+ virtual osg::ref_ptr<ossimPlanetImage> getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility);
+
+ void setServer(const std::string& serverString);
+ const std::string& getServer()const;
+ const std::string& getImageType()const;
+ void setImageType(const std::string& imageType);
+
+ void setCacheDirectory(const ossimFilename& cacheDir);
+ const ossimFilename& getCacheDirectory()const;
+ const ossimFilename& getCompleteCacheDirectory()const;
+
+ void setRawCapabilities(const ossimString& rawCapabilities);
+ const ossimString& getRawCapabilities()const;
+
+ void setCapabilitiesUrl(const std::string& url);
+ const std::string& getCapabilitiesUrl()const;
+
+ void setBackgroundColor(const ossimString& color);
+ const ossimString& getBackgroundColor()const;
+
+ void setTransparentFlag(bool flag);
+ bool getTransparentFlag()const;
+
+ void setAdditionalParameters(const ossimString& additionalParameters);
+ const ossimString& getAdditionalParameters()const;
+
+ void setAutoCreateCacheFlag(bool value);
+ bool getAutoCreateCacheFlag()const;
+
+ void clearDiskCache();
+
+ virtual ossimRefPtr<ossimXmlNode> saveXml(bool recurse=true)const;
+ bool loadXml(ossimRefPtr<ossimXmlNode> node);
+
+ void setProxyHost(const std::string& host)
+ {
+ theProxyHost = host;
+ theWmsClient->setProxyHost(host);
+ }
+ void setProxyPort(const std::string& port)
+ {
+ theProxyPort = port;
+ theWmsClient->setProxyPort(port);
+ }
+ void setProxyUser(const std::string& user)
+ {
+ theProxyUser = user;
+ theWmsClient->setProxyUser(user);
+ }
+ void setProxyPassword(const std::string& password)
+ {
+ theProxyPassword = password;
+ theWmsClient->setProxyPassword(password);
+ }
+ const std::string& proxyHost()const
+ {
+ return theProxyHost;
+ }
+ const std::string& proxyPort()const
+ {
+ return theProxyPort;
+ }
+ const std::string& proxyUser()const
+ {
+ return theProxyUser;
+ }
+ const std::string& proxyPassword()const
+ {
+ return theProxyPassword;
+ }
+
+protected:
+ void adjustServerString();
+
+ ossimFilename theCacheDirectory;
+ ossimFilename theCompleteCacheDirectory;
+ ossimString theServer;
+ ossimString theAdjustedServer;
+ ossimString theImageType;
+ ossimString theRawCapabilities;
+ ossimString theCapabilitiesUrl;
+ ossimString theBackgroundColor;
+ bool theTransparentFlag;
+ ossimString theAdditionalParameters;
+ std::string theProxyHost;
+ std::string theProxyPort;
+ std::string theProxyUser;
+ std::string theProxyPassword;
+ mutable ossimPlanetReentrantMutex theWmsArchiveMutex;
+ std::vector<ossimString> theLayers;
+ std::vector<ossimString> theStyles;
+ bool theAutoCreateCacheFlag;
+ ossimRefPtr<ossimImageFileWriter> theWriter;
+ osg::ref_ptr<ossimPlanetWmsClient> theWmsClient;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetXmlAction.h b/ossimPlanet/include/ossimPlanet/ossimPlanetXmlAction.h
new file mode 100644
index 0000000..4b4765e
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetXmlAction.h
@@ -0,0 +1,81 @@
+#ifndef ossimPlanetXmlAction_HEADER
+#define ossimPlanetXmlAction_HEADER
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <osg/ref_ptr>
+
+class OSSIMPLANET_DLL ossimPlanetXmlAction : public ossimPlanetAction
+{
+public:
+ ossimPlanetXmlAction(const ossimString& code = ossimString(),
+ const ossimString& originatingFederate = defaultOrigin());
+ ossimPlanetXmlAction(ossimRefPtr<ossimXmlNode> node,
+ const ossimString& originatingFederate = defaultOrigin());
+ ossimPlanetXmlAction(const ossimPlanetXmlAction& src)
+ :ossimPlanetAction(src),
+ theXmlNode(src.theXmlNode.valid()?(ossimXmlNode*)src.theXmlNode->dup():(ossimXmlNode*)0)
+ {
+
+ }
+ virtual ossimPlanetAction* clone()const
+ {
+ return new ossimPlanetXmlAction(*this);
+ }
+ virtual ossimPlanetAction* cloneType()const
+ {
+ return new ossimPlanetXmlAction();
+ }
+ virtual ossimPlanetXmlAction* toXmlAction()
+ {
+ return this;
+ }
+ virtual const ossimPlanetXmlAction* toXmlAction()const
+ {
+ return this;
+ }
+ virtual void setTarget(const ossimString& value);
+ virtual void setCommand(const ossimString& value);
+
+ /**
+ * Will allow one to set the source code for the derived actions
+ *
+ */
+ virtual bool setSourceCode(const ossimString& code);
+ ossimRefPtr<ossimXmlNode> xmlNode()
+ {
+ return theXmlNode;
+ }
+ const ossimRefPtr<ossimXmlNode> xmlNode()const
+ {
+ return theXmlNode;
+ }
+ void setXmlNode(ossimRefPtr<ossimXmlNode> code);
+
+ /**
+ * Utility method for accessing the attribute id of the Action.
+ */
+ ossimString id()const;
+ ossimString name()const;
+
+ /**
+ * Utility method to duplicte a child of the action and maintain the same action parameters
+ */
+ osg::ref_ptr<ossimPlanetXmlAction> duplicateChildAndMaintainAction(ossim_uint32 childIdx)const;
+
+ /**
+ * Utility method to duplicate the child properties and promote them as the children of the Action.
+ * This is typically used when doing a set Action on a node. The properties are promoted for the set actions
+ *
+ */
+ osg::ref_ptr<ossimPlanetXmlAction> duplicateChildPropertiesAndMaintainAction(ossim_uint32 childIdx)const;
+
+ bool hasChildren()const;
+ virtual void print(std::ostream& out)const;
+ virtual void read(std::istream& in);
+
+protected:
+ ossimRefPtr<ossimXmlNode> theXmlNode;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/ossimPlanetYahooGeocoder.h b/ossimPlanet/include/ossimPlanet/ossimPlanetYahooGeocoder.h
new file mode 100644
index 0000000..17aa476
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ossimPlanetYahooGeocoder.h
@@ -0,0 +1,23 @@
+#ifndef ossimPlanetYahooGeocoder_HEADER
+#define ossimPlanetYahooGeocoder_HEADER
+#include <ossimPlanet/ossimPlanetGeocoder.h>
+#include <ossimPlanet/ossimPlanetExport.h>
+
+class OSSIMPLANET_DLL ossimPlanetYahooGeocoder : public ossimPlanetGoecoder
+{
+public:
+ ossimPlanetYahooGeocoder(const ossimString url = "http://api.local.yahoo.com/MapsService/V1/geocode?",
+ const ossimString yahooAppId = "YahooDemo")
+ :theUrl(url),
+ theAppId(yahooAppId)
+ {
+ }
+ virtual void getLocationFromAddress(std::vector<osg::ref_ptr<ossimPlanetGeocoderLocation> >& result,
+ const ossimString& location)const;
+
+protected:
+ ossimString theUrl;
+ ossimString theAppId;
+};
+
+#endif
diff --git a/ossimPlanet/include/ossimPlanet/sg_file.h b/ossimPlanet/include/ossimPlanet/sg_file.h
new file mode 100644
index 0000000..1755a9a
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/sg_file.h
@@ -0,0 +1,101 @@
+/** \file sg_file.hxx
+ * File I/O routines.
+ */
+
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: sg_file.h 10524 2007-02-26 18:27:24Z gpotts $
+
+
+#ifndef _SG_FILE_HXX
+#define _SG_FILE_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <ossimPlanet/compiler.h>
+
+#include <string>
+
+#include <sys/types.h> // for open(), read(), write(), close()
+#include <sys/stat.h> // for open(), read(), write(), close()
+#include <fcntl.h> // for open(), read(), write(), close()
+#if !defined( _MSC_VER )
+# include <unistd.h> // for open(), read(), write(), close()
+#endif
+
+#include "iochannel.h"
+
+SG_USING_STD(string);
+
+
+/**
+ * A file I/O class based on SGIOChannel.
+ */
+class SGFile : public SGIOChannel {
+
+ string file_name;
+ int fp;
+ bool eof_flag;
+
+public:
+
+ /**
+ * Create an instance of SGFile.
+ * When calling the constructor you need to provide a file
+ * name. This file is not opened immediately, but instead will be
+ * opened when the open() method is called.
+ * @param file name of file to open
+ */
+ SGFile( const string& file );
+
+ /** Destructor */
+ ~SGFile();
+
+ // open the file based on specified direction
+ bool open( const SGProtocolDir dir );
+
+ // read a block of data of specified size
+ int read( char *buf, int length );
+
+ // read a line of data, length is max size of input buffer
+ int readline( char *buf, int length );
+
+ // write data to a file
+ int write( const char *buf, const int length );
+
+ // write null terminated string to a file
+ int writestring( const char *str );
+
+ // close file
+ bool close();
+
+ /** @return the name of the file being manipulated. */
+ inline string get_file_name() const { return file_name; }
+
+ /** @return true of eof conditions exists */
+ inline bool eof() const { return eof_flag; };
+};
+
+
+#endif // _SG_FILE_HXX
+
+
diff --git a/ossimPlanet/include/ossimPlanet/sg_socket.h b/ossimPlanet/include/ossimPlanet/sg_socket.h
new file mode 100644
index 0000000..b6bbc05
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/sg_socket.h
@@ -0,0 +1,181 @@
+/**
+ * \file sg_socket.hxx
+ * Socket I/O routines.
+ */
+
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: sg_socket.h 10927 2007-05-16 13:22:06Z gpotts $
+
+
+#ifndef _SG_SOCKET_HXX
+#define _SG_SOCKET_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+#include <vector>
+
+#include <ossimPlanet/compiler.h>
+
+#include STL_STRING
+
+#include "iochannel.h"
+
+#include "netSocket.h"
+
+SG_USING_STD(string);
+
+#include <vector>
+#define SG_MAX_SOCKET_QUEUE 32
+
+
+/**
+ * A socket I/O class based on SGIOChannel.
+ */
+class SGSocket : public SGIOChannel {
+public:
+private:
+ string hostname;
+ string port_str;
+
+ std::vector<char> save_buf;
+/* char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ]; */
+ int save_len;
+
+ netSocket sock;
+ netSocket* client;
+ unsigned short port;
+ bool is_tcp;
+ bool is_server;
+ bool first_read;
+ int timeout;
+
+ /**
+ * Not used yet. Will allow the buffer to grow instead of stay fixed.
+ */
+ bool theAutoGrowFlag;
+
+ static bool init;
+
+ // make a server (master listening) socket
+ bool make_server_socket();
+
+ // make a client socket
+ bool make_client_socket();
+
+ // Poll for new connections or data to read.
+ int poll();
+
+public:
+
+ /**
+ * Create an instance of SGSocket.
+ *
+ * When calling the constructor you need to provide a host name, a
+ * port number, and a socket style. The convention used by the
+ * SGSocket class is that the server side listens and the client
+ * side sends. For a server socket, the host name should be
+ * empty. For a server, the port number is optional, if you do not
+ * specify a port, the system will assign one. For a client
+ * socket, you need to specify both a destination host and
+ * destination port. For both client and server sockets you must
+ * specify the socket type. Type must be either udp or tcp. Here's
+ * a quick breakdown of the major differences between UDP and TCP
+ * type sockets.
+ *
+ * TCP sockets are the type where you establish a connection and
+ * then can read and write to the socket from both ends. If one
+ * end of TCP socket connect quits, the other end will likely
+ * segfault if it doesn't take special precautions. But, the nice
+ * thing about TCP connections is that the underlying protocol
+ * guarantees that your message will get through. This imposes a
+ * certain performance overhead though on the communication
+ * because the protocol must resend failed messages. TCP sockets
+ * are good for sending periodic command/response type messages
+ * where performance isn't a big issues, but reliability is.
+ *
+ * UDP sockets on the other hand are a lower level protocol and
+ * don't have the same sort of connection as TCP sockets. With UDP
+ * sockets, the server end just sits and listens for incoming
+ * packets from anywhere. The client end sends it's message and
+ * forgets about it. It doesn't care if there isn't even a server
+ * out there listening and all the packets are getting
+ * lost. Although systems/networks usually do a pretty good job
+ * (statistically) of getting your UDP packets to their
+ * destination, there is no guarantee that any particular packet
+ * will make it. But, because of this low level implementation and
+ * lack of error checking, UDP packets are much faster and
+ * efficient. UDP packets are good for sending positional
+ * information to synchronize two applications. In this case, you
+ * want the information to arrive as quickly as possible, and if
+ * you lose a packet, you'd rather get new updated information
+ * rather than have the system waste time resending a packet that
+ * is becoming older and older with every retry.
+ * @param host name of host if direction is SG_IO_OUT or SG_IO_BI
+ * @param port port number if we care to choose one.
+ * @param style specify "udp" or "tcp"
+ */
+ SGSocket( const string& host, const string& port, const string& style );
+ SGSocket();
+ /** Destructor */
+ ~SGSocket();
+
+ virtual void setSocket(const string& host, const string& port, const string& style);
+ virtual void setSocket(const string& host, int port, const string& style);
+ // If specified as a server (in direction for now) open the master
+ // listening socket. If specified as a client (out direction),
+ // open a connection to a server.
+ bool open( const SGProtocolDir d );
+
+ // read data from socket
+ int read( char *buf, int length );
+
+ // read data from socket
+ int readline( char *buf, int length );
+
+ // write data to a socket
+ int write( const char *buf, const int length );
+
+ // write null terminated string to a socket
+ int writestring( const char *str );
+
+ // close file
+ bool close();
+
+ /**
+ * Enable non-blocking mode.
+ * @return success/failure
+ */
+ bool nonblock();
+
+ // set timeout (default: 0)
+ inline void set_timeout(int i) { timeout = i; }
+
+ /** @return the remote host name */
+ inline string get_hostname() const { return hostname; }
+
+ /** @return the port number (in string form) */
+ inline string get_port_str() const { return port_str; }
+ inline std::string get_port_style()const { return is_tcp?"tcp":"udp";}
+};
+
+
+#endif // _SG_SOCKET_HXX
diff --git a/ossimPlanet/include/ossimPlanet/sg_socket_udp.h b/ossimPlanet/include/ossimPlanet/sg_socket_udp.h
new file mode 100644
index 0000000..cfd8271
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/sg_socket_udp.h
@@ -0,0 +1,137 @@
+/**
+ * \file sg_socket_udp.hxx
+ * UDP Socket I/O routines.
+ */
+
+// Written by Curtis Olson, started November 2001.
+//
+// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: sg_socket_udp.h 10524 2007-02-26 18:27:24Z gpotts $
+
+
+#ifndef _SG_SOCKET_UDP_HXX
+#define _SG_SOCKET_UDP_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include "netSocket.h"
+
+#include <ossimPlanet/compiler.h>
+
+#include STL_STRING
+
+#include <ossimPlanet/iochannel.h>
+
+SG_USING_STD(string);
+
+/**
+ * A UDP socket I/O class based on SGIOChannel and plib/net.
+ */
+class SGSocketUDP : public SGIOChannel {
+
+private:
+
+ netSocket sock;
+
+ string hostname;
+ string port_str;
+
+ char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
+ int save_len;
+
+ short unsigned int port;
+
+public:
+
+ /**
+ * Create an instance of SGSocketUDP.
+ *
+ * When calling the constructor you need to provide a host name, and a
+ * port number. The convention used by the
+ * SGSocketUDP class is that the server side listens and the client
+ * side sends. For a server socket, the host name should be
+ * empty. For a server, the port number is optional, if you do not
+ * specify a port, the system will assign one. For a client
+ * socket, you need to specify both a destination host and
+ * destination port.
+ *
+ * UDP sockets are a lower level protocol than TCP sockets and are
+ * "connectionless" in the sense that either client or server can
+ * exist, or not exist, startup, quit, etc. in any order and
+ * whenever both ends are alive, the communication succeeds. With
+ * UDP sockets, the server end just sits and listens for incoming
+ * packets from anywhere. The client end sends it's message and
+ * forgets about it. It doesn't care if there isn't even a server
+ * out there listening and all the packets are getting
+ * lost. Although systems/networks usually do a pretty good job
+ * (statistically) of getting your UDP packets to their
+ * destination, there is no guarantee that any particular packet
+ * will make it. But, because of this low level implementation and
+ * lack of error checking, UDP packets are much faster and
+ * efficient. UDP packets are good for sending positional
+ * information to synchronize two applications. In this case, you
+ * want the information to arrive as quickly as possible, and if
+ * you lose a packet, you'd rather get new updated information
+ * rather than have the system waste time resending a packet that
+ * is becoming older and older with every retry.
+ * @param host name of host if direction is SG_IO_OUT or SG_IO_BI
+ * @param port port number if we care to choose one.
+ * @param style specify "udp" or "tcp" */
+ SGSocketUDP( const string& host, const string& port );
+
+ /** Destructor */
+ ~SGSocketUDP();
+
+ // If specified as a server (in direction for now) open the master
+ // listening socket. If specified as a client (out direction),
+ // open a connection to a server.
+ bool open( const SGProtocolDir d );
+
+ // read data from socket
+ int read( char *buf, int length );
+
+ // read data from socket
+ int readline( char *buf, int length );
+
+ // write data to a socket
+ int write( const char *buf, const int length );
+
+ // write null terminated string to a socket
+ int writestring( const char *str );
+
+ // close file
+ bool close();
+
+ /**
+ * Set blocking true or false
+ * @return success/failure
+ */
+ bool setBlocking( bool value );
+
+ /** @return the remote host name */
+ inline string get_hostname() const { return hostname; }
+
+ /** @return the port number (in string form) */
+ inline string get_port_str() const { return port_str; }
+};
+
+
+#endif // _SG_SOCKET_UDP_HXX
diff --git a/ossimPlanet/include/ossimPlanet/ul.h b/ossimPlanet/include/ossimPlanet/ul.h
new file mode 100644
index 0000000..26d3cf3
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ul.h
@@ -0,0 +1,868 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ul.h 2117 2007-09-13 23:21:09Z fayjf $
+*/
+
+//
+// UL - utility library
+//
+// Contains:
+// - necessary system includes
+// - basic types
+// - error message routines
+// - high performance clocks
+// - ulList
+// - ulLinkedList
+// - more to come (endian support, version ID)
+//
+
+#ifndef _INCLUDED_UL_H_
+#define _INCLUDED_UL_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+/**********************\
+* *
+* Determine OS type *
+* *
+\**********************/
+
+#if defined(__CYGWIN__)
+
+#define UL_WIN32 1
+#define UL_CYGWIN 1 /* Windoze AND Cygwin. */
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER)
+
+#define UL_WIN32 1
+#define UL_MSVC 1 /* Windoze AND MSVC. */
+
+#elif defined(__BEOS__)
+
+#define UL_BEOS 1
+
+#elif defined( macintosh )
+
+#define UL_MACINTOSH 1
+
+#elif defined(__APPLE__)
+
+#define UL_MAC_OSX 1
+
+#elif defined(__linux__)
+
+#define UL_LINUX 1
+
+#elif defined(__sgi)
+
+#define UL_IRIX 1
+
+#elif defined(_AIX)
+
+#define UL_AIX 1
+
+#elif defined(SOLARIS) || defined(sun)
+
+#define UL_SOLARIS 1
+
+#elif defined(hpux)
+
+#define UL_HPUX 1
+
+#elif (defined(__unix__) || defined(unix)) && !defined(USG)
+
+#define UL_BSD 1
+
+#endif
+
+
+/*
+ Add specialised includes/defines...
+*/
+
+#ifdef UL_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <mmsystem.h>
+#include <regstr.h>
+#define UL_WGL 1
+#endif
+
+#ifdef UL_CYGWIN
+#include <unistd.h>
+#define UL_WGL 1
+#endif
+
+#ifdef UL_BEOS
+#include <be/kernel/image.h>
+#define UL_GLX 1
+#endif
+
+#ifdef UL_MACINTOSH
+#include <CodeFragments.h>
+#include <unistd.h>
+#define UL_AGL 1
+#endif
+
+#ifdef UL_MAC_OSX
+#include <unistd.h>
+#define UL_CGL 1
+#endif
+
+#if defined(UL_LINUX) || defined(UL_BSD) || defined(UL_IRIX) || defined(UL_SOLARIS) || defined(UL_AIX)
+#include <unistd.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#define UL_GLX 1
+#endif
+
+#if defined(UL_BSD)
+#include <sys/param.h>
+#define UL_GLX 1
+#endif
+
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
+#include <float.h>
+#include <errno.h>
+
+/* PLIB version macros */
+
+#define PLIB_MAJOR_VERSION 1
+#define PLIB_MINOR_VERSION 8
+#define PLIB_TINY_VERSION 5
+
+#define PLIB_VERSION (PLIB_MAJOR_VERSION*100 \
+ +PLIB_MINOR_VERSION*10 \
+ +PLIB_TINY_VERSION)
+
+/* SGI machines seem to suffer from a lack of FLT_EPSILON so... */
+
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19209290e-07f
+#endif
+
+#ifndef DBL_EPSILON
+#define DBL_EPSILON 1.19209290e-07f
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/* SUNWspro 4.2 and earlier need bool to be defined */
+
+#if defined(__SUNPRO_CC) && __SUNPRO_CC < 0x500
+typedef int bool ;
+const int true = 1 ;
+const int false = 0 ;
+#endif
+
+/* Let's define our own "min" and "max" so that different operating systems
+ * don't complain
+ */
+#define ulMax(a,b) ((a)>(b)?(a):(b))
+#define ulMin(a,b) ((a)<(b)?(a):(b))
+
+
+/*
+ Basic Types
+*/
+
+
+/*
+ High precision clocks.
+*/
+
+class ulClock
+{
+ double start ;
+ double now ;
+ double delta ;
+ double last_time ;
+ double max_delta ;
+
+#ifdef UL_WIN32
+ static double res ;
+ static int perf_timer ;
+ void initPerformanceTimer () ;
+#endif
+
+ double getRawTime () const ;
+
+public:
+
+ ulClock () { reset () ; }
+
+ void reset ()
+ {
+#ifdef UL_WIN32
+ initPerformanceTimer () ;
+#endif
+ start = getRawTime () ;
+ now = 0.0 ;
+ max_delta = 0.2 ;
+ delta = 0.0000001 ; /* Faked so stoopid programs won't div0 */
+ last_time = 0.0 ;
+ }
+
+ void setMaxDelta ( double maxDelta ) { max_delta = maxDelta ; }
+ double getMaxDelta () const { return max_delta ; }
+ void update () ;
+ double getAbsTime () const { return now ; }
+ double getDeltaTime () const { return delta ; }
+ double getFrameRate () const { return 1.0 / delta ; }
+} ;
+
+
+inline void ulSleep ( int seconds )
+{
+ if ( seconds >= 0 )
+ {
+#ifdef UL_WIN32
+ Sleep ( 1000 * seconds ) ;
+#else
+ sleep ( seconds ) ;
+#endif
+ }
+}
+
+
+inline void ulMilliSecondSleep ( int milliseconds )
+{
+ if ( milliseconds >= 0 )
+ {
+#ifdef UL_WIN32
+ Sleep ( milliseconds ) ;
+#else
+ usleep ( milliseconds * 1000 ) ;
+#endif
+ }
+}
+
+inline void ulMicroSecondSleep ( int microseconds )
+{
+ if ( microseconds >= 0 )
+ {
+#ifdef UL_WIN32
+ Sleep ( microseconds/1000 ) ;
+#else
+ usleep ( microseconds) ;
+#endif
+ }
+}
+
+
+/*
+ This is extern C to enable 'configure.in' to
+ find it with a C-coded probe.
+*/
+
+extern "C" void ulInit () ;
+
+/*
+ Error handler.
+*/
+
+enum ulSeverity
+{
+ UL_DEBUG, // Messages that can safely be ignored.
+ UL_WARNING, // Messages that are important.
+ UL_FATAL, // Errors that we cannot recover from.
+ UL_MAX_SEVERITY
+} ;
+
+
+typedef void (*ulErrorCallback) ( enum ulSeverity severity, char* msg ) ;
+
+void ulSetError ( enum ulSeverity severity, const char *fmt, ... ) ;
+char* ulGetError ( void ) ;
+void ulClearError ( void ) ;
+ulErrorCallback ulGetErrorCallback ( void ) ;
+void ulSetErrorCallback ( ulErrorCallback cb ) ;
+
+/*
+ Directory Reading
+*/
+
+#define UL_NAME_MAX 256
+typedef struct _ulDir ulDir ;
+struct ulDirEnt
+{
+ char d_name [ UL_NAME_MAX+1 ];
+ bool d_isdir ;
+} ;
+
+int ulIsAbsolutePathName ( const char *pathname ) ;
+char *ulGetCWD ( char *result, int maxlength ) ;
+
+ulDir* ulOpenDir ( const char* dirname ) ;
+ulDirEnt* ulReadDir ( ulDir* dir ) ;
+void ulCloseDir ( ulDir* dir ) ;
+
+// file handling
+
+char* ulMakePath( char* path, const char* dir, const char* fname );
+
+bool ulFileExists ( const char *fileName ) ;
+
+void ulFindFile( char *filenameOutput, const char *path,
+ const char * tfnameInput, const char *sAPOM ) ;
+
+
+/*
+ Endian handling
+*/
+
+static const int _ulEndianTest = 1;
+#define ulIsLittleEndian (*((char *) &_ulEndianTest ) != 0)
+#define ulIsBigEndian (*((char *) &_ulEndianTest ) == 0)
+
+inline void ulEndianSwap(unsigned int *x)
+{
+ *x = (( *x >> 24 ) & 0x000000FF ) |
+ (( *x >> 8 ) & 0x0000FF00 ) |
+ (( *x << 8 ) & 0x00FF0000 ) |
+ (( *x << 24 ) & 0xFF000000 ) ;
+}
+
+
+inline void ulEndianSwap(unsigned short *x)
+{
+ *x = (( *x >> 8 ) & 0x00FF ) |
+ (( *x << 8 ) & 0xFF00 ) ;
+}
+
+
+inline void ulEndianSwap(float *x) { ulEndianSwap((unsigned int *)x); }
+inline void ulEndianSwap(int *x) { ulEndianSwap((unsigned int *)x); }
+inline void ulEndianSwap(short *x) { ulEndianSwap((unsigned short *)x); }
+
+
+inline unsigned short ulEndianLittle16(unsigned short x) {
+ if (ulIsLittleEndian) {
+ return x;
+ } else {
+ ulEndianSwap(&x);
+ return x;
+ }
+}
+
+inline unsigned int ulEndianLittle32(unsigned int x) {
+ if (ulIsLittleEndian) {
+ return x;
+ } else {
+ ulEndianSwap(&x);
+ return x;
+ }
+}
+
+inline float ulEndianLittleFloat(float x) {
+ if (ulIsLittleEndian) {
+ return x;
+ } else {
+ ulEndianSwap(&x);
+ return x;
+ }
+}
+
+inline void ulEndianLittleArray16(unsigned short *x, int length) {
+ if (ulIsLittleEndian) {
+ return;
+ } else {
+ for (int i = 0; i < length; i++) {
+ ulEndianSwap(x++);
+ }
+ }
+}
+
+inline void ulEndianLittleArray32(unsigned int *x, int length) {
+ if (ulIsLittleEndian) {
+ return;
+ } else {
+ for (int i = 0; i < length; i++) {
+ ulEndianSwap(x++);
+ }
+ }
+}
+
+inline void ulEndianLittleArrayFloat(float *x, int length) {
+ if (ulIsLittleEndian) {
+ return;
+ } else {
+ for (int i = 0; i < length; i++) {
+ ulEndianSwap(x++);
+ }
+ }
+}
+
+inline void ulEndianBigArray16(unsigned short *x, int length) {
+ if (ulIsBigEndian) {
+ return;
+ } else {
+ for (int i = 0; i < length; i++) {
+ ulEndianSwap(x++);
+ }
+ }
+}
+
+inline void ulEndianBigArray32(unsigned int *x, int length) {
+ if (ulIsBigEndian) {
+ return;
+ } else {
+ for (int i = 0; i < length; i++) {
+ ulEndianSwap(x++);
+ }
+ }
+}
+
+inline void ulEndianBigArrayFloat(float *x, int length) {
+ if (ulIsBigEndian) {
+ return;
+ } else {
+ for (int i = 0; i < length; i++) {
+ ulEndianSwap(x++);
+ }
+ }
+}
+
+inline unsigned short ulEndianBig16(unsigned short x) {
+ if (ulIsBigEndian) {
+ return x;
+ } else {
+ ulEndianSwap(&x);
+ return x;
+ }
+}
+
+inline unsigned int ulEndianBig32(unsigned int x) {
+ if (ulIsBigEndian) {
+ return x;
+ } else {
+ ulEndianSwap(&x);
+ return x;
+ }
+}
+
+inline float ulEndianBigFloat(float x) {
+ if (ulIsBigEndian) {
+ return x;
+ } else {
+ ulEndianSwap(&x);
+ return x;
+ }
+}
+
+inline unsigned short ulEndianReadLittle16(FILE *f) {
+ unsigned short x;
+ fread(&x, 2, 1, f);
+ return ulEndianLittle16(x);
+}
+
+inline unsigned int ulEndianReadLittle32(FILE *f) {
+ unsigned int x;
+ fread(&x, 4, 1, f);
+ return ulEndianLittle32(x);
+}
+
+inline float ulEndianReadLittleFloat(FILE *f) {
+ float x;
+ fread(&x, 4, 1, f);
+ return ulEndianLittleFloat(x);
+}
+
+inline unsigned short ulEndianReadBig16(FILE *f) {
+ unsigned short x;
+ fread(&x, 2, 1, f);
+ return ulEndianBig16(x);
+}
+
+inline unsigned int ulEndianReadBig32(FILE *f) {
+ unsigned int x;
+ fread(&x, 4, 1, f);
+ return ulEndianBig32(x);
+}
+
+inline float ulEndianReadBigFloat(FILE *f) {
+ float x;
+ fread(&x, 4, 1, f);
+ return ulEndianBigFloat(x);
+}
+
+inline size_t ulEndianWriteLittle16(FILE *f, unsigned short x) {
+ x = ulEndianLittle16(x);
+ return fwrite( &x, 2, 1, f );
+}
+
+inline size_t ulEndianWriteLittle32(FILE *f, unsigned int x) {
+ x = ulEndianLittle32(x);
+ return fwrite( &x, 4, 1, f );
+}
+
+inline size_t ulEndianWriteLittleFloat(FILE *f, float x) {
+ x = ulEndianLittleFloat(x);
+ return fwrite( &x, 4, 1, f );
+}
+
+inline size_t ulEndianWriteBig16(FILE *f, unsigned short x) {
+ x = ulEndianBig16(x);
+ return fwrite( &x, 2, 1, f );
+}
+
+inline size_t ulEndianWriteBig32(FILE *f, unsigned int x) {
+ x = ulEndianBig32(x);
+ return fwrite( &x, 4, 1, f );
+}
+
+inline size_t ulEndianWriteBigFloat(FILE *f, float x) {
+ x = ulEndianBigFloat(x);
+ return fwrite( &x, 4, 1, f );
+}
+
+
+/*
+ Windoze/BEOS code based on contribution from Sean L. Palmer
+*/
+
+
+#ifdef UL_WIN32
+
+class ulDynamicLibrary
+{
+ HMODULE handle ;
+
+public:
+
+ ulDynamicLibrary ( const char *libname )
+ {
+ char dllname[1024];
+ strcpy ( dllname, libname ) ;
+ strcat ( dllname, ".dll" ) ;
+#ifdef UL_WIN32
+ handle = (HMODULE) LoadLibraryA ( (char*)dllname ) ;
+#else
+ handle = (HMODULE) LoadLibrary ( (char*)dllname ) ;
+
+#endif
+ }
+
+ void *getFuncAddress ( const char *funcname )
+ {
+ return (void *) GetProcAddress ( handle, funcname ) ; //lint !e611
+ }
+
+ ~ulDynamicLibrary ()
+ {
+ if ( handle != NULL )
+ FreeLibrary ( handle ) ;
+ }
+} ;
+
+#elif defined (UL_MACINTOSH)
+
+class ulDynamicLibrary
+{
+ CFragConnectionID connection;
+ OSStatus error;
+
+public:
+
+ ulDynamicLibrary ( const char *libname )
+ {
+ Str63 pstr;
+ int sz;
+
+ sz = strlen (libname);
+
+ if (sz < 64) {
+
+ pstr[0] = sz;
+ memcpy (pstr+1, libname, sz);
+
+ error = GetSharedLibrary (pstr, kPowerPCCFragArch, kReferenceCFrag,
+ &connection, NULL, NULL);
+ }
+ else
+ error = 1;
+ }
+
+ ~ulDynamicLibrary ()
+ {
+ if ( ! error )
+ CloseConnection (&connection);
+ }
+
+ void* getFuncAddress ( const char *funcname )
+ {
+ if ( ! error ) {
+
+ char* addr;
+ Str255 sym;
+ int sz;
+
+ sz = strlen (funcname);
+ if (sz < 256) {
+
+ sym[0] = sz;
+ memcpy (sym+1, funcname, sz);
+
+ error = FindSymbol (connection, sym, &addr, 0);
+ if ( ! error )
+ return addr;
+ }
+ }
+
+ return NULL;
+ }
+};
+
+#elif defined (UL_MAC_OSX)
+
+
+class ulDynamicLibrary
+{
+
+ public:
+
+ ulDynamicLibrary ( const char *libname )
+ {
+ }
+
+ ~ulDynamicLibrary ()
+ {
+ }
+
+ void* getFuncAddress ( const char *funcname )
+ {
+ ulSetError ( UL_WARNING, "ulDynamicLibrary unsuppored on Mac OS X" );
+ return NULL;
+ }
+};
+
+#elif defined (__BEOS__)
+
+class ulDynamicLibrary
+{
+ image_id *handle ;
+
+public:
+
+ ulDynamicLibrary ( const char *libname )
+ {
+ char addonname[1024] ;
+ strcpy ( addonname, libname ) ;
+ strcat ( addonname, ".so" ) ;
+ handle = new image_id ;
+
+ *handle = load_add_on ( addonname ) ;
+
+ if ( *handle == B_ERROR )
+ {
+ delete handle ;
+ handle = NULL ;
+ }
+ }
+
+ void *getFuncAddress ( const char *funcname )
+ {
+ void *sym = NULL ;
+
+ if ( handle &&
+ get_image_symbol ( handle, "funcname",
+ B_SYMBOL_TYPE_TEXT, &sym ) == B_NO_ERROR )
+ return sym ;
+
+ return NULL ;
+ }
+
+ ~ulDynamicLibrary ()
+ {
+ if ( handle != NULL )
+ unload_add_on ( handle ) ;
+
+ delete handle ;
+ }
+} ;
+
+# else
+
+/*
+ Linux/UNIX
+*/
+
+class ulDynamicLibrary
+{
+ void *handle ;
+
+public:
+
+ ulDynamicLibrary ( const char *libname )
+ {
+ char dsoname [ 1024 ] ;
+ strcpy ( dsoname, libname ) ;
+ strcat ( dsoname, ".so" ) ;
+ handle = (void *) dlopen ( dsoname, RTLD_NOW | RTLD_GLOBAL ) ;
+
+ if ( handle == NULL )
+ ulSetError ( UL_WARNING, "ulDynamicLibrary: %s\n", dlerror() ) ;
+ }
+
+ void *getFuncAddress ( const char *funcname )
+ {
+ return (handle==NULL) ? NULL : dlsym ( handle, funcname ) ;
+ }
+
+ ~ulDynamicLibrary ()
+ {
+ if ( handle != NULL )
+ dlclose ( handle ) ;
+ }
+} ;
+
+#endif
+
+
+class ulList
+{
+protected:
+ unsigned int total ; /* The total number of entities in the list */
+ unsigned int limit ; /* The current limit on number of entities */
+ unsigned int next ; /* The next entity when we are doing getNext ops */
+
+ void **entity_list ; /* The list. */
+
+ void sizeChk (void) ;
+
+public:
+
+ ulList ( int init_max = 1 ) ;
+ virtual ~ulList (void) ;
+
+ void *getEntity ( unsigned int n )
+ {
+ next = n + 1 ;
+ return ( n >= total ) ? (void *) NULL : entity_list [ n ] ;
+ }
+
+ virtual void addEntity ( void *entity ) ;
+ virtual void addEntityBefore ( int n, void *entity ) ;
+ virtual void removeEntity ( unsigned int n ) ;
+
+ void removeAllEntities () ;
+
+ void removeEntity ( void *entity )
+ {
+ removeEntity ( searchForEntity ( entity ) ) ;
+ }
+
+ virtual void replaceEntity ( unsigned int n, void *new_entity ) ;
+
+ void replaceEntity ( void *old_entity, void *new_entity )
+ {
+ replaceEntity ( searchForEntity ( old_entity ), new_entity ) ;
+ }
+
+ void *getNextEntity (void) { return getEntity ( next ) ; }
+
+ int getNumEntities (void) const { return total ; }
+ int searchForEntity ( void *entity ) const ;
+} ;
+
+
+typedef bool (*ulIterateFunc)( const void *data, void *user_data ) ;
+typedef int (*ulCompareFunc)( const void *data1, const void *data2 ) ;
+
+/*
+ Linked list.
+*/
+
+class ulListNode ;
+
+class ulLinkedList
+{
+protected:
+
+ ulListNode *head ;
+ ulListNode *tail ;
+
+ int nnodes ;
+ bool sorted ;
+
+ void unlinkNode ( ulListNode *prev, ulListNode *node ) ;
+
+ bool isValidPosition ( int pos ) const
+ {
+ if ( ( pos < 0 ) || ( pos >= nnodes ) )
+ {
+ ulSetError ( UL_WARNING, "ulLinkedList: Invalid 'pos' %u", pos ) ;
+ return false ;
+ }
+ return true ;
+ }
+
+public:
+
+ ulLinkedList ()
+ {
+ head = tail = NULL ;
+ nnodes = 0 ;
+ sorted = true ;
+ }
+
+ ~ulLinkedList () { empty () ; }
+
+ int getNumNodes ( void ) const { return nnodes ; }
+ bool isSorted ( void ) const { return sorted ; }
+
+ int getNodePosition ( void *data ) const ;
+
+ void insertNode ( void *data, int pos ) ;
+ void prependNode ( void *data ) { insertNode ( data, 0 ) ; }
+ void appendNode ( void *data ) ;
+
+ int insertSorted ( void *data, ulCompareFunc comparefn ) ;
+
+ void removeNode ( void *data ) ;
+ void * removeNode ( int pos ) ;
+
+ void * getNodeData ( int pos ) const ;
+
+ void * forEach ( ulIterateFunc fn, void *user_data = NULL ) const ;
+
+ void empty ( ulIterateFunc destroyfn = NULL, void *user_data = NULL ) ;
+} ;
+
+
+extern char *ulStrDup ( const char *s ) ;
+extern int ulStrNEqual ( const char *s1, const char *s2, int len );
+extern int ulStrEqual ( const char *s1, const char *s2 );
+
+//lint -restore
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ulLocal.h b/ossimPlanet/include/ossimPlanet/ulLocal.h
new file mode 100644
index 0000000..e7e7cea
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ulLocal.h
@@ -0,0 +1,52 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ulLocal.h 1568 2002-09-02 06:05:49Z sjbaker $
+*/
+
+#ifndef _UL_LOCAL_H_
+#define _UL_LOCAL_H_ 1
+
+#include "ul.h"
+
+class ulListNode
+{
+protected:
+
+ ulListNode *next ;
+ void *data ;
+
+public:
+
+ ulListNode ( void *dt, ulListNode *next_node )
+ {
+ data = dt ;
+ next = next_node ;
+ }
+
+ void * getData ( void ) const { return data ; }
+ void setData ( void *d ) { data = d ; }
+
+ ulListNode * getNext ( void ) const { return next ; }
+ void setNext ( ulListNode *n ) { next = n ; }
+} ;
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/ulRTTI.h b/ossimPlanet/include/ossimPlanet/ulRTTI.h
new file mode 100644
index 0000000..e8c5216
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/ulRTTI.h
@@ -0,0 +1,420 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net */
+
+
+/*
+ Originally written by: Alexandru C. Telea <alext at win.tue.nl>
+*/
+
+/*
+ This file provides support for RTTI and generalized (virtual-base to derived
+ and separate hierarchy branches) casting. There is also support for RT obj
+ creation from type names.
+
+ In order to enable these features for a class, two things should be done:
+
+ 1) insert the text UL_TYPE_DATA (without ';') in the class-decl.
+ 2) in the .C file where the class's implementation resides, insert the
+ following (without';'):
+
+ UL_RTTI_DEF(classname)
+ if the class has no bases with RTTI
+
+ UL_RTTI_DEFn(classname,b1,...bn)
+ if the class has bases b1,...bn with RTTI
+
+ Use UL_RTTI_DEF_INST instead of UL_RTTI_DEF if you want to enable RT
+ obj creation for classname. You should provide then a public default
+ ctor.
+
+ RTTI is used via a class called ulRTTItypeid. A typeid describes a type of a
+ class. [..] They should provide all necessary support for any kind of
+ RTTI/casting [..].
+
+ [..]
+
+ REMARK: There are two classes related to RTTI: ulRTTItypeid and
+ ======= ulRTTITypeinfo. A ulRTTItypeid is, as it says, an 'id for a
+ type'. It actually wraps a ulRTTITypeinfo*, where a
+ ulRTTITypeinfo contains the actual encoding of a class type.
+ You can freely create/copy/destroy/manipulate ulRTTItypeid's,
+ but you should NEVER deal directly with ulRTTITypeinfo. A
+ ulRTTITypeinfo should actually be created ONLY by the
+ UL_TYPE_DATA macros, as part of a class definition, since the
+ ulRTTITypeinfo encodes a type info for an EXISTING class [..].
+ All type-related stuff should be therefore handled via
+ ulRTTItypeid's.
+*/
+
+#ifndef _UL_RTTI_H_
+#define _UL_RTTI_H_
+
+#include <string.h>
+#include "ul.h"
+
+
+class ulRTTITypeinfo
+/* Implementation of type-related info */
+{
+private:
+
+ char *n ; /* type name */
+
+ /*
+ base types (NULL-ended array of ulRTTITypeinfo's for this's direct bases)
+ */
+ const ulRTTITypeinfo** b ;
+
+ int ns ; /* #subtypes of this type */
+ const ulRTTITypeinfo **subtypes ; /* types derived from this type */
+
+ /* convenience type info for a 'null' type */
+ static const ulRTTITypeinfo null_type ;
+
+ void* (*new_obj)() ; /* func to create a new obj of this type */
+ void* (*cast)(int,void*) ; /*
+ func to cast an obj of this type to ith
+ baseclass of it or to itself
+ */
+
+ /* adds a subtype to this's subtypes[] */
+ void add_subtype ( const ulRTTITypeinfo * ) ;
+
+ /* dels a subtype from this's subtypes[] */
+ void del_subtype ( const ulRTTITypeinfo* ) ;
+
+ friend class ulRTTItypeid ; /* for null_type */
+
+public:
+
+ ulRTTITypeinfo ( const char* name, const ulRTTITypeinfo* bb[],
+ void* (*)(int,void*),void* (*)() ) ;
+ ~ulRTTITypeinfo () ;
+
+ /* Returns name of this ulRTTITypeinfo */
+ const char* getname () const { return n ; }
+
+ /* Compares 2 ulRTTITypeinfo objs */
+ bool same ( const ulRTTITypeinfo *p ) const
+ {
+ /*
+ First, try to see if it's the same 'physical' ulRTTITypeinfo (which
+ should be the case, since we create them per-class and not per-obj).
+ */
+ return ( this == p ) || !strcmp ( n, p->n ) ;
+ }
+
+ /* true if the arg can be cast to this, else false */
+ bool can_cast ( const ulRTTITypeinfo *p ) const
+ {
+ return same ( p ) || p->has_base ( this ) ;
+ }
+
+ /* true if this has the arg as some base, else false */
+ bool has_base ( const ulRTTITypeinfo *p ) const
+ {
+ for ( int i = 0 ; b[i] != NULL ; i++ ) /* for all bases of this... */
+ /* match found, return 1 or no match, search deeper */
+ if ( p->same ( b[i] ) || b[i]->has_base ( p ) ) return true ;
+ return false ; /* no match at all, return false */
+ }
+
+ /* get i-th subclass of this, if any, else NULL */
+ const ulRTTITypeinfo * subclass ( int i = 0 ) const
+ {
+ return ( i >= 0 && i < ns ) ? subtypes[i] : NULL ;
+ }
+
+ int num_subclasses () const { return ns ; } /* get # subclasses of this */
+
+ /*
+ search for a subclass named char*, create obj of it and return it cast to
+ the ulRTTITypeinfo* type, which is either this or a direct base of this.
+ */
+ void * create ( const ulRTTITypeinfo *, const char * ) const ;
+
+ /* Returns true if this type has a default ctor, else false */
+ bool can_create () const { return new_obj != NULL ; }
+} ;
+
+
+class ulRTTItypeid
+/* Main class for RTTI interface */
+{
+protected:
+
+ /* ulRTTItypeid implementation (the only data-member) */
+ const ulRTTITypeinfo* id ;
+
+public:
+
+ /* Not for application use ! */
+ const ulRTTITypeinfo* get_info () const { return id ; }
+
+ ulRTTItypeid ( const ulRTTITypeinfo* p ) : id ( p ) { }
+ ulRTTItypeid () : id ( &ulRTTITypeinfo::null_type ) { }
+
+ /* Compares 2 ulRTTItypeid objs */
+ bool isSame ( ulRTTItypeid i ) const { return id->same ( i.id ) ; }
+
+ /* true if the arg can be cast to this, else false */
+ bool canCast ( ulRTTItypeid i ) const { return id->can_cast ( i.id ) ; }
+
+ const char * getName () const { return id->getname () ; }
+
+ /* Return # subclasses of this */
+ int getNumSubclasses () const { return id->num_subclasses () ; }
+
+ /* Return ith subclass of this */
+ ulRTTItypeid getSubclass ( int i ) const { return id->subclass ( i ) ; }
+
+ /* Return # baseclasses of this */
+ int getNumBaseclasses () const
+ {
+ int i ; for ( i = 0 ; id->b[i] != NULL ; i++ ) ;
+ return i ;
+ }
+
+ /* Return ith baseclass of this */
+ ulRTTItypeid getBaseclass ( int i ) const { return id->b[i] ; }
+
+ /*
+ Tries to create an instance of a subclass of this having of type given
+ by the ulRTTItypeid arg. If ok, it returns it casted to the class-type of
+ this and then to void*
+ */
+ void * create ( ulRTTItypeid t ) const
+ {
+ return id->create ( id, t.getName () ) ;
+ }
+
+ /* Returns true if this type is instantiable, else false */
+ bool canCreate () const { return id->can_create () ; }
+} ;
+
+
+class ulRTTIdyntypeid : public ulRTTItypeid
+/*
+ Class for dynamic type creation from user strings. Useful for creating
+ typeids at RT for comparison purposes.
+*/
+{
+private:
+
+ static const ulRTTITypeinfo *a[] ;
+
+public:
+
+ ulRTTIdyntypeid ( const char *c ) :
+ /* create a dummy ulRTTITypeinfo */
+ ulRTTItypeid ( new ulRTTITypeinfo ( c, a, NULL, NULL ) ) { }
+
+ ~ulRTTIdyntypeid () { delete id ; /* delete the dummy ulRTTITypeinfo */ }
+} ;
+
+
+
+/*
+ Macros
+*/
+
+/*
+ 'ulRTTItypeid'
+ UL_STATIC_TYPE_INFO(T) T=RTTI-class name.
+ Returns a ulRTTItypeid with T's type. If T
+ hasn't RTTI, a compile-time error occurs.
+*/
+
+#define UL_STATIC_TYPE_INFO(T) T::RTTI_sinfo()
+
+
+/*
+ 'T*'
+ UL_PTR_CAST(T,p) T=RTTI-class, p=RTTI-class ptr.
+ Returns p cast to the type T as a T*, if cast is
+ possible, else returns NULL. If *p or T have no RTTI,
+ a compile-time error occurs. Note that p can point to
+ virtual base classes. Casting between separat branches
+ of a class hierarchy is also supported, as long as all
+ classes have RTTI. Therefore UL_PTR_CAST is a fully
+ general and safe operator. If p==NULL, the operator
+ returns NULL.
+*/
+
+#define UL_PTR_CAST(T,p) ((p != NULL)? (T*)((p)->RTTI_cast(UL_STATIC_TYPE_INFO(T))) : NULL)
+
+
+/* 'T*'
+ UL_TYPE_NEW(T,t) T=RTTI-class, t=ulRTTItypeid
+ Returns a new object of type t cast to the type T as
+ a T*. t must represent a type identical to or derived
+ from T. If t is not a type derived from T or not an
+ instantiable type having a default constructor, NULL is
+ returned. */
+
+#define UL_TYPE_NEW(T,t) ((T*)t.create(T))
+
+
+
+/*
+ Definition of TYPE_DATA for a RTTI-class: introduces one static
+ ulRTTITypeinfo data-member and a couple of virtuals.
+*/
+
+#define UL_TYPE_DATA \
+ protected: \
+ static const ulRTTITypeinfo RTTI_obj; \
+ static void* RTTI_scast(int,void*); \
+ static void* RTTI_new(); \
+ virtual ulRTTItypeid RTTI_vinfo() const { return &RTTI_obj; }\
+ public: \
+ static ulRTTItypeid RTTI_sinfo() { return &RTTI_obj; }\
+ virtual void* RTTI_cast(ulRTTItypeid);
+
+
+
+/*
+ Definition of auxiliary data-structs supporting RTTI for a class: defines
+ the static ulRTTITypeinfo object of that class and its associated virtuals.
+*/
+
+/* Auxiliary definition of the construction method: */
+#define UL_RTTI_NEW(cls) void* cls::RTTI_new() { return new cls; } \
+ const ulRTTITypeinfo cls::RTTI_obj(#cls,RTTI_base_ ## cls,cls::RTTI_scast,cls::RTTI_new);
+
+#define UL_RTTI_NO_NEW(cls) const ulRTTITypeinfo cls::RTTI_obj(#cls,RTTI_base_ ## cls,cls::RTTI_scast,NULL);
+
+
+
+/*
+ Top-level macros:
+*/
+
+#define UL_RTTI_DEF_BASE(cls) \
+ static const ulRTTITypeinfo* RTTI_base_ ## cls [] = { NULL }; \
+ void* cls::RTTI_cast(ulRTTItypeid t) \
+ { \
+ if (t.isSame(&RTTI_obj)) return this; \
+ return NULL; \
+ } \
+ void* cls::RTTI_scast(int i,void* p) \
+ { cls* ptr = (cls*)p; return ptr; }
+
+
+#define UL_RTTI_DEF1_BASE(cls,b1) \
+ static const ulRTTITypeinfo* RTTI_base_ ## cls [] = \
+ { UL_STATIC_TYPE_INFO(b1).get_info(), NULL }; \
+ void* cls::RTTI_cast(ulRTTItypeid t) \
+ { \
+ if (t.isSame(&RTTI_obj)) return this; \
+ void* ptr; \
+ if ((ptr=b1::RTTI_cast(t))) return ptr; \
+ return NULL; \
+ } \
+ void* cls::RTTI_scast(int i,void* p) \
+ { cls* ptr = (cls*)p; \
+ switch(i) \
+ { case 0: return (b1*)ptr; } \
+ return ptr; \
+ }
+
+
+#define UL_RTTI_DEF2_BASE(cls,b1,b2) \
+ static const ulRTTITypeinfo* RTTI_base_ ## cls [] = \
+ { UL_STATIC_TYPE_INFO(b1).get_info(), \
+ UL_STATIC_TYPE_INFO(b2).get_info(), NULL }; \
+ void* cls::RTTI_cast(ulRTTItypeid t) \
+ { \
+ if (t.isSame(&RTTI_obj)) return this; \
+ void* ptr; \
+ if ((ptr=b1::RTTI_cast(t))) return ptr; \
+ if ((ptr=b2::RTTI_cast(t))) return ptr; \
+ return NULL; \
+ } \
+ void* cls::RTTI_scast(int i,void* p) \
+ { cls* ptr = (cls*)p; \
+ switch(i) \
+ { case 0: return (b1*)ptr; \
+ case 1: return (b2*)ptr; \
+ } \
+ return ptr; \
+ }
+
+#define UL_RTTI_DEF3_BASE(cls,b1,b2,b3) \
+ static const ulRTTITypeinfo* RTTI_base_ ## cls [] = \
+ { UL_STATIC_TYPE_INFO(b1).get_info(), \
+ UL_STATIC_TYPE_INFO(b2).get_info(), \
+ UL_STATIC_TYPE_INFO(b3).get_info(), NULL }; \
+ void* cls::RTTI_cast(ulRTTItypeid t) \
+ { \
+ if (t.isSame(&RTTI_obj)) return this; \
+ void* ptr; \
+ if ((ptr=b1::RTTI_cast(t))) return ptr; \
+ if ((ptr=b2::RTTI_cast(t))) return ptr; \
+ if ((ptr=b3::RTTI_cast(t))) return ptr; \
+ return NULL; \
+ } \
+ void* cls::RTTI_scast(int i,void* p) \
+ { cls* ptr = (cls*)p; \
+ switch(i) \
+ { case 0: return (b1*)ptr; \
+ case 1: return (b2*)ptr; \
+ case 2: return (b3*)ptr; \
+ } \
+ return ptr; \
+ }
+
+
+
+#define UL_RTTI_DEF_INST(cls) \
+ UL_RTTI_DEF_BASE(cls) \
+ UL_RTTI_NEW(cls)
+
+#define UL_RTTI_DEF(cls) \
+ UL_RTTI_DEF_BASE(cls) \
+ UL_RTTI_NO_NEW(cls)
+
+#define UL_RTTI_DEF1_INST(cls,b1) \
+ UL_RTTI_DEF1_BASE(cls,b1) \
+ UL_RTTI_NEW(cls)
+
+#define UL_RTTI_DEF1(cls,b1) \
+ UL_RTTI_DEF1_BASE(cls,b1) \
+ UL_RTTI_NO_NEW(cls)
+
+#define UL_RTTI_DEF2_INST(cls,b1,b2) \
+ UL_RTTI_DEF2_BASE(cls,b1,b2) \
+ UL_RTTI_NEW(cls)
+
+#define UL_RTTI_DEF2(cls,b1,b2) \
+ UL_RTTI_DEF2_BASE(cls,b1,b2) \
+ UL_RTTI_NO_NEW(cls)
+
+#define UL_RTTI_DEF3_INST(cls,b1,b2,b3) \
+ UL_RTTI_DEF3_BASE(cls,b1,b2,b3) \
+ UL_RTTI_NEW(cls)
+
+#define UL_RTTI_DEF3(cls,b1,b2,b3) \
+ UL_RTTI_DEF3_BASE(cls,b1,b2,b3) \
+ UL_RTTI_NO_NEW(cls)
+
+
+#endif
+
diff --git a/ossimPlanet/include/ossimPlanet/unzip.h b/ossimPlanet/include/ossimPlanet/unzip.h
new file mode 100644
index 0000000..3573be2
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/unzip.h
@@ -0,0 +1,354 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+ WinZip, InfoZip tools and compatible.
+
+ Multi volume ZipFile (span) are not supported.
+ Encryption compatible with pkzip 2.04g only supported
+ Old compressions used by old PKZip 1.x are not supported
+
+
+ I WAIT FEEDBACK at mail info at winimage.com
+ Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+
+/* for more info about .ZIP format, see
+ http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+ http://www.info-zip.org/pub/infozip/doc/
+ PkWare has also a specification at :
+ ftp://ftp.pkware.com/probdesc.zip
+*/
+
+#ifndef _unz_H
+#define _unz_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include <ossimPlanet/ioapi.h>
+#endif
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity));
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+ "zlib/zlib113.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
+/*
+ Open a Zip file, like unzOpen, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity));
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+ uLong pos_in_zip_directory; /* offset in zip file directory */
+ uLong num_of_file; /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+ const char* password));
+/*
+ Open for reading data the current file in the zipfile.
+ password is a crypting password
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw,
+ const char* password));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz_H */
diff --git a/ossimPlanet/include/ossimPlanet/zip.h b/ossimPlanet/include/ossimPlanet/zip.h
new file mode 100644
index 0000000..b0bcff4
--- /dev/null
+++ b/ossimPlanet/include/ossimPlanet/zip.h
@@ -0,0 +1,235 @@
+/* zip.h -- IO for compress .zip files using zlib
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
+ WinZip, InfoZip tools and compatible.
+ Multi volume ZipFile (span) are not supported.
+ Encryption compatible with pkzip 2.04g only supported
+ Old compressions used by old PKZip 1.x are not supported
+
+ For uncompress .zip file, look at unzip.h
+
+
+ I WAIT FEEDBACK at mail info at winimage.com
+ Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+
+/* for more info about .ZIP format, see
+ http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+ http://www.info-zip.org/pub/infozip/doc/
+ PkWare has also a specification at :
+ ftp://ftp.pkware.com/probdesc.zip
+*/
+
+#ifndef _zip_H
+#define _zip_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include <ossimPlanet/ioapi.h>
+#endif
+
+#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagzipFile__ { int unused; } zipFile__;
+typedef zipFile__ *zipFile;
+#else
+typedef voidp zipFile;
+#endif
+
+#define ZIP_OK (0)
+#define ZIP_EOF (0)
+#define ZIP_ERRNO (Z_ERRNO)
+#define ZIP_PARAMERROR (-102)
+#define ZIP_BADZIPFILE (-103)
+#define ZIP_INTERNALERROR (-104)
+
+#ifndef DEF_MEM_LEVEL
+# if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+# else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+# endif
+#endif
+/* default memLevel */
+
+/* tm_zip contain date/time info */
+typedef struct tm_zip_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_zip;
+
+typedef struct
+{
+ tm_zip tmz_date; /* date in understandable format */
+ uLong dosDate; /* if dos_date == 0, tmu_date is used */
+/* uLong flag; */ /* general purpose bit flag 2 bytes */
+
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+} zip_fileinfo;
+
+typedef const char* zipcharpc;
+
+
+#define APPEND_STATUS_CREATE (0)
+#define APPEND_STATUS_CREATEAFTER (1)
+#define APPEND_STATUS_ADDINZIP (2)
+
+extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
+/*
+ Create a zipfile.
+ pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
+ an Unix computer "zlib/zlib113.zip".
+ if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
+ will be created at the end of the file.
+ (useful if the file contain a self extractor code)
+ if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
+ add files in existing zip (be sure you don't add file that doesn't exist)
+ If the zipfile cannot be opened, the return value is NULL.
+ Else, the return value is a zipFile Handle, usable with other function
+ of this zip package.
+*/
+
+/* Note : there is no delete function into a zipfile.
+ If you want delete file into a zipfile, you must open a zipfile, and create another
+ Of couse, you can use RAW reading and writing to copy the file you did not want delte
+*/
+
+extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
+ int append,
+ zipcharpc* globalcomment,
+ zlib_filefunc_def* pzlib_filefunc_def));
+
+extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
+ const char* filename,
+ const zip_fileinfo* zipfi,
+ const void* extrafield_local,
+ uInt size_extrafield_local,
+ const void* extrafield_global,
+ uInt size_extrafield_global,
+ const char* comment,
+ int method,
+ int level));
+/*
+ Open a file in the ZIP for writing.
+ filename : the filename in zip (if NULL, '-' without quote will be used
+ *zipfi contain supplemental information
+ if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
+ contains the extrafield data the the local header
+ if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
+ contains the extrafield data the the local header
+ if comment != NULL, comment contain the comment string
+ method contain the compression method (0 for store, Z_DEFLATED for deflate)
+ level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
+*/
+
+
+extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
+ const char* filename,
+ const zip_fileinfo* zipfi,
+ const void* extrafield_local,
+ uInt size_extrafield_local,
+ const void* extrafield_global,
+ uInt size_extrafield_global,
+ const char* comment,
+ int method,
+ int level,
+ int raw));
+
+/*
+ Same than zipOpenNewFileInZip, except if raw=1, we write raw file
+ */
+
+extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
+ const char* filename,
+ const zip_fileinfo* zipfi,
+ const void* extrafield_local,
+ uInt size_extrafield_local,
+ const void* extrafield_global,
+ uInt size_extrafield_global,
+ const char* comment,
+ int method,
+ int level,
+ int raw,
+ int windowBits,
+ int memLevel,
+ int strategy,
+ const char* password,
+ uLong crcForCtypting));
+
+/*
+ Same than zipOpenNewFileInZip2, except
+ windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
+ password : crypting password (NULL for no crypting)
+ crcForCtypting : crc of file to compress (needed for crypting)
+ */
+
+
+extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
+ const void* buf,
+ unsigned len));
+/*
+ Write data in the zipfile
+*/
+
+extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
+/*
+ Close the current file in the zipfile
+*/
+
+extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
+ uLong uncompressed_size,
+ uLong crc32));
+/*
+ Close the current file in the zipfile, for fiel opened with
+ parameter raw=1 in zipOpenNewFileInZip2
+ uncompressed_size and crc32 are value for the uncompressed size
+*/
+
+extern int ZEXPORT zipClose OF((zipFile file,
+ const char* global_comment));
+/*
+ Close the zipfile
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _zip_H */
diff --git a/ossimPlanet/projects/vs2005/ossimPlanet.sln b/ossimPlanet/projects/vs2005/ossimPlanet.sln
new file mode 100644
index 0000000..c60efb2
--- /dev/null
+++ b/ossimPlanet/projects/vs2005/ossimPlanet.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ossimPlanet", "ossimPlanet.vcproj", "{F042D695-C4DD-4282-B22F-A3041AB93623}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ossimplanetviewer", "..\..\examples\ossimplanetviewer\ossimplanetviewer.vcproj", "{982CDBCD-0217-4E0D-8870-338D101EB982}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F042D695-C4DD-4282-B22F-A3041AB93623} = {F042D695-C4DD-4282-B22F-A3041AB93623}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug using Release|Win32 = Debug using Release|Win32
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F042D695-C4DD-4282-B22F-A3041AB93623}.Debug using Release|Win32.ActiveCfg = Debug using Release|Win32
+ {F042D695-C4DD-4282-B22F-A3041AB93623}.Debug using Release|Win32.Build.0 = Debug using Release|Win32
+ {F042D695-C4DD-4282-B22F-A3041AB93623}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F042D695-C4DD-4282-B22F-A3041AB93623}.Debug|Win32.Build.0 = Debug|Win32
+ {F042D695-C4DD-4282-B22F-A3041AB93623}.Release|Win32.ActiveCfg = Release|Win32
+ {F042D695-C4DD-4282-B22F-A3041AB93623}.Release|Win32.Build.0 = Release|Win32
+ {982CDBCD-0217-4E0D-8870-338D101EB982}.Debug using Release|Win32.ActiveCfg = Release|Win32
+ {982CDBCD-0217-4E0D-8870-338D101EB982}.Debug using Release|Win32.Build.0 = Release|Win32
+ {982CDBCD-0217-4E0D-8870-338D101EB982}.Debug|Win32.ActiveCfg = Debug|Win32
+ {982CDBCD-0217-4E0D-8870-338D101EB982}.Debug|Win32.Build.0 = Debug|Win32
+ {982CDBCD-0217-4E0D-8870-338D101EB982}.Release|Win32.ActiveCfg = Release|Win32
+ {982CDBCD-0217-4E0D-8870-338D101EB982}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/ossimPlanet/projects/vs2005/ossimPlanet.vcproj b/ossimPlanet/projects/vs2005/ossimPlanet.vcproj
new file mode 100644
index 0000000..d75a184
--- /dev/null
+++ b/ossimPlanet/projects/vs2005/ossimPlanet.vcproj
@@ -0,0 +1,1381 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="ossimPlanet"
+ ProjectGUID="{F042D695-C4DD-4282-B22F-A3041AB93623}"
+ RootNamespace="ossimPlanet"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)\out\Debug"
+ IntermediateDirectory="$(OutDir)\work\$(ProjectName)\"
+ ConfigurationType="2"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\..\ossim_dependencies\src\3rdParty\include";"$(ProjectDir)..\..\..\ossim\include";"$(ProjectDir)..\..\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\zziplib-0.13.49";"$(ProjectDir)..\..\..\libwms\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph\include""
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OSSIMPLANET_LIBRARY;ssize_t=int"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ AssemblerListingLocation="$(IntDir)"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="ossimd.lib OpenThreadsWin32d.lib Producerd.lib osgd.lib osgDBd.lib osgGAd.lib osgTextd.lib osgUtild.lib libwmsd.lib libjpegD.lib Ws2_32.lib Winmm.lib"
+ OutputFile="$(OutDir)\bin\$(ProjectName)d.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=".\out\Release\lib;"$(OutDir)\lib";..\src\OpenSceneGraph\lib\win32"
+ GenerateDebugInformation="true"
+ SubSystem="0"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)\lib\ossimPlanetd.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir "$(SolutionDir)..\..\include\win32"
xcopy /Y /S "$(SolutionDir)..\src\ossimPlanet\include" "$(SolutionDir)..\..\include\win32"
"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)\work\$(ProjectName)\"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ WholeProgramOptimization="false"
+ AdditionalIncludeDirectories=""$(InputDir)..\..\include";"$(InputDir)..\..\..\libwms\include";"$(InputDir)..\..\..\ossim\include";"$(InputDir)..\..\..\ossimPredator\include";"$(InputDir)..\..\..\ossim_dependencies\include";"$(InputDir)..\..\..\ossim_dependencies\include\freetype";"$(InputDir)..\..\..\ossim_dependencies\src\ffmpeg""
+ PreprocessorDefinitions="WIN32;_LIB;NDEBUG;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;OSSIMPLANET_LIBRARY;ssize_t=int;OSSIMPLANET_ENABLE_PREDATOR;OSSIMPLANET_ENABLE_EPHEMERIS"
+ StringPooling="false"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib1.lib OpenThreads.lib osg.lib osgDB.lib osgGA.lib osgText.lib osgUtil.lib osgViewer.lib libjpeg.lib Ws2_32.lib Winmm.lib opengl32.lib gpstk.lib"
+ OutputFile="$(OutDir)\bin\$(ProjectName).dll"
+ AdditionalLibraryDirectories=""$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph-2.8.1\build\lib";"$(ProjectDir)..\..\..\ossim_dependencies\lib""
+ IgnoreDefaultLibraryNames="LIBCMT.lib"
+ GenerateDebugInformation="true"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)\lib\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug using Release|Win32"
+ OutputDirectory="$(SolutionDir)\out\Debug"
+ IntermediateDirectory="$(OutDir)\work\$(ProjectName)\"
+ ConfigurationType="2"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\..\ossim_dependencies\src\3rdParty\include";"$(ProjectDir)..\..\..\ossim\include";"$(ProjectDir)..\..\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\zziplib-0.13.49";"$(ProjectDir)..\..\..\libwms\include";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph\include""
+ PreprocessorDefinitions="WIN32;_LIB;_CRT_SECURE_NO_DEPRECATE;OSSIMPLANET_LIBRARY;ssize_t=int"
+ StringPooling="true"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ AssemblerListingLocation="$(IntDir)"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="ossim.lib OpenThreadsWin32.lib Producer.lib osg.lib osgDB.lib osgGA.lib osgText.lib osgUtil.lib libwms.lib libjpeg.lib Ws2_32.lib Winmm.lib zzlib.lib"
+ OutputFile="$(OutDir)\bin\$(ProjectName)d.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""$(ProjectDir)..\..\..\ossim\projects\vs2005\bin\Release";.\out\Release\lib;"$(OutDir)\lib";"$(ProjectDir)..\..\..\ossim_dependencies\src\OpenSceneGraph\lib\win32""
+ GenerateDebugInformation="true"
+ SubSystem="0"
+ OptimizeForWindows98="0"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)\lib\ossimPlanetd.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir "$(SolutionDir)..\..\include\win32"
xcopy /Y /S "$(SolutionDir)..\src\ossimPlanet\include" "$(SolutionDir)..\..\include\win32"
pushlib.bat "$(OutDir)\lib\ossimPlanetd.lib" "$(OutDir)\bin\ossimPlanetd.dll"
"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\src\ossimPlanet\ioapi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\iochannel.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\iowin32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\mkUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\netBuffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\netChannel.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\netChat.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\netMessage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\netMonitor.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\netSocket.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanet.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetAction.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetActionReceiver.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetActionRouter.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetAnimatedPointModel.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetAnimationPath.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetAnnotationLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetAnnotationLayerNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetApi.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetArchive.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetArchiveMapping.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetBillboardIcon.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetBoundingBox.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetCache.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetClientThread.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetCloudLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetCompass.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetCubeGrid.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetDatabasePager.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetDestinationCommandAction.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetDtedElevationDatabase.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetElevationDatabase.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetElevationDatabaseGroup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetElevationFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetElevationGrid.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetElevationRegistry.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetEphemeris.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetFadeText.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetGeneralRasterElevationDatabase.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetGeocoder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetGrid.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetGridUtility.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetIconGeom.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetId.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetIdManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetInteractionController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetIoRoutableMessageHandler.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetIoSocket.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetIoSocketServerChannel.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetIoThread.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetJpegImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetKml.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetKmlLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetKmlLayerNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetKmlNetworkLinkNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetKmlPlacemarkNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetKmlScreenOverlayNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLabelGeom.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLand.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLandCache.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLandCullCallback.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLandReaderWriter.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLatLonHud.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLayerFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLayerRegistry.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLookAt.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetLsrSpaceTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetManipulator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetNavigator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetNodeFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetNodeRegistry.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetOperation.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetOssimElevationDatabase.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetOssimImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetOssimImageLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetPagedLandLod.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetPlaneGrid.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetPointModel.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetPredatorVideoLayerNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetSceneView.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetServerThread.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetShaderProgramSetup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetSocketNetworkConnection.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetSousaLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetSrtmElevationDatabase.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetStandardTextureLayerFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTerrain.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTerrainGeometryTechnique.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTerrainLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTerrainTechnique.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTerrainTile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTexture2D.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTextureLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTextureLayerGroup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTextureLayerRegistry.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetThread.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetThreadImp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetThreadPool.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetTileRequest.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetUtility.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetVideoLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetViewer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetViewMatrixBuilder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetVisitors.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetWmsClient.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetWmsImageLayer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetXmlAction.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ossimPlanetYahooGeocoder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\sg_file.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\sg_socket.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\sg_socket_udp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ul.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ulClock.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ulError.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ulLinkedList.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ulList.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\ulRTTI.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\unzip.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\zip.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <File
+ RelativePath="..\..\include\ossimPlanet\compiler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ossimPlanet\crypt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ioapi.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\iochannel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\iowin32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\mkUtils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\net.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\netBuffer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\netChannel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\netChat.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\netMessage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\netMonitor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\netSocket.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanet.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetAction.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetActionReceiver.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetActionRouter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetAnimatedPointModel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetAnimationPath.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetAnnotationLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetAnnotationLayerNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetApi.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetArchive.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetArchiveMapping.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetBillboardIcon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetBoundingBox.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetCache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetCallback.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetClientThread.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetCloudLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetCompass.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetConstants.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetCubeGrid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetDatabasePager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetDestinationCommandAction.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetDtedElevationDatabase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetElevationDatabase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetElevationDatabaseGroup.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetElevationFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetElevationGrid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetElevationRegistry.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetEphemeris.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetExport.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetExtents.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetFadeText.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetGeneralRasterElevationDatabase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetGeocoder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetGeoRefModel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetGrid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetGridUtility.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIconGeom.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetId.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIdManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIdolBridge.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIdolLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetImage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetInputDevice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetInteractionController.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIntersectUserData.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIo.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIoMessageHandler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIoRoutableMessageHandler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIoSocket.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIoSocketServerChannel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetIoThread.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetJpegImage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKml.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKmlLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKmlLayerNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKmlNetworkLinkNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKmlPlacemarkNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKmlReaderWriter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetKmlScreenOverlayNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLabelGeom.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLand.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandCache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandCullCallback.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandNormalType.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandReaderWriter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandTextureRequest.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLandTreeNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLatLonHud.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLayerFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLayerFactoryBase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLayerRegistry.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLookAt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetLsrSpaceTransform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetManipulator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetMessage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetNavigator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetNetworkConnection.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetNodeFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetNodeFactoryBase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetNodeRegistry.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetOperation.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetOrthoFlatLandNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetOssimElevationDatabase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetOssimImage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetOssimImageLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPagedLandLod.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPagedLandLodRefreshType.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPagedRequestNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPlaneGrid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPointModel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPredatorVideoLayerNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetPrimaryBody.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetReentrantMutex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetRefBlock.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetSceneView.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetServerMessageHandler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetServerThread.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetSetup.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetShaderProgramSetup.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetSocketNetworkConnection.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetSousaLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetSrtmElevationDatabase.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetStandardTextureLayerFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTerrain.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTerrainGeometryTechnique.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTerrainLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTerrainTechnique.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTerrainTile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTerrainTileId.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTexture2D.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTextureLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTextureLayerFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTextureLayerGroup.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTextureLayerRegistry.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetThread.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetThreadImp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetThreadPool.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetTileRequest.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetUtility.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetVideoLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetVideoLayerNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetViewer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetViewMatrixBuilder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetVisitors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetWmsClient.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetWmsImageLayer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetXmlAction.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ossimPlanetYahooGeocoder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\sg_file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\sg_socket.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\sg_socket_udp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ul.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ulLocal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\ulRTTI.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\unzip.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\include\ossimPlanet\zip.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/ossimPlanet/schema/AnimationPath.xsd b/ossimPlanet/schema/AnimationPath.xsd
new file mode 100644
index 0000000..640a6ef
--- /dev/null
+++ b/ossimPlanet/schema/AnimationPath.xsd
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleType name="pathCoordinatesType">
+ <xs:list itemType="xs:string"/>
+ </xs:simpleType>
+ <xs:simpleType name="orientationType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="lsrhpr"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="positionType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="latlonhgt"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="timeUnitEnumType" >
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="seconds"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:element name="GeospatialPath" type="GeospatialPathType"/>
+ <xs:complexType name="GeospatialPathType">
+ <xs:sequence>
+ <xs:element name="description" type="xs:string"/>
+ <xs:element name="coordinates" type="pathCoordinatesType" minOccurs="1" maxOccurs="1"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="id" use="optional"/>
+ <xs:attribute name="refId" use="optional"/>
+ <xs:attribute name="timeUnit" type="timeUnitEnumType" use="required"/>
+ <xs:attribute name="positionType" type="positionType" use="required"/>
+ <xs:attribute name="orientationType" type="orientationType" use="required"/>
+ <xs:attribute name="timestamp" type="xs:dateTime" use="optional"/>
+ <xs:attribute name="duration" type="xs:duration" use="optional"/>
+ </xs:complexType>
+ <xs:element name="AnimationPath" type="AnimationPathType" abstract="false"/>
+ <xs:complexType name="AnimationPathType" abstract="false">
+ <xs:sequence>
+ <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element ref="GeospatialPath" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ <xs:attribute name="refId" type="xs:string" use="optional"/>
+ <xs:attribute name="id" type="xs:string" use="optional"/>
+ <xs:attribute name="parentId" type="xs:string" use="optional"/>
+ <xs:attribute name="timeScale" type="xs:double" use="optional"/>
+ <xs:attribute name="timeOffset" type="xs:duration" use="optional"/>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git a/ossimPlanet/schema/ossimPlanet.xsd b/ossimPlanet/schema/ossimPlanet.xsd
new file mode 100644
index 0000000..efbd128
--- /dev/null
+++ b/ossimPlanet/schema/ossimPlanet.xsd
@@ -0,0 +1,447 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="AbstractObjectGroup" type="AbstractObjectType" abstract="true"/>
+ <xs:complexType name="AbstractObjectType" abstract="true">
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0" maxOccurs="1"> </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="optional"> </xs:attribute>
+ <xs:attribute name="parentId" type="xs:string" use="optional"> </xs:attribute>
+ </xs:complexType>
+ <xs:element name="address" type="xs:string" default=""/>
+ <xs:element name="range" type="xs:double" default="0.0"/>
+ <xs:element name="longitude" type="angle180Type" default="0.0"/>
+ <xs:element name="latitude" type="angle90Type" default="0.0"/>
+ <xs:element name="altitude" type="xs:double" default="0.0"/>
+ <xs:attribute name="vref">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="wgs84"/>
+ <xs:enumeration value="msl"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="groupType">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="groundTexture"/>
+ <xs:enumeration value="feature"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:simpleType name="objectType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Placemark"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="heading" type="angle360Type" default="0.0"/>
+ <xs:element name="pitch" type="angle180Type" default="0.0"/>
+ <xs:element name="roll" type="angle180Type" default="0.0"/>
+ <xs:simpleType name="anglepos90Type">
+ <xs:restriction base="xs:double">
+ <xs:minInclusive value="0.0"/>
+ <xs:maxInclusive value="90.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="angle90Type">
+ <xs:restriction base="xs:double">
+ <xs:minInclusive value="-90"/>
+ <xs:maxInclusive value="90.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="anglepos180Type">
+ <xs:restriction base="xs:double">
+ <xs:minInclusive value="0.0"/>
+ <xs:maxInclusive value="180.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="angle180Type">
+ <xs:restriction base="xs:double">
+ <xs:minInclusive value="-180.0"/>
+ <xs:maxInclusive value="180.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="angle360Type">
+ <xs:restriction base="xs:double">
+ <xs:minInclusive value="-360.0"/>
+ <xs:maxInclusive value="360.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="metaKeyEnumType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="shift"/>
+ <xs:enumeration value="ctrl"/>
+ <xs:enumeration value="alt"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="KeyType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value=".|space|delete|return|home|escape|right|left|up|down"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="mouseButtonType">
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="mouseButtonStateEnumType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="press"/>
+ <xs:enumeration value="release"/>
+ <xs:enumeration value="doubleClick"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="filename" type="xs:string"></xs:element>
+ <xs:element name="extrude" type="xs:boolean" default="0"/>
+ <xs:simpleType name="altitudeModeEnumType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="clampToGround"/>
+ <xs:enumeration value="relativeToGround"/>
+ <xs:enumeration value="absolute"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="timeUnitEnumType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="seconds"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="AbstractInputDeviceGroup" type="AbstractInputDeviceType" abstract="true"/>
+ <xs:complexType name="AbstractInputDeviceType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType">
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Link" type="LinkType" substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="LinkType">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType">
+ <xs:sequence>
+ </xs:sequence>
+ <xs:attribute name="href" type="xs:anyURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Keyboard" type="KeyboardType" abstract="false" final="#all"
+ substitutionGroup="AbstractInputDeviceGroup"/>
+ <xs:complexType name="KeyboardType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractInputDeviceType">
+ <xs:attribute name="key" type="KeyType" use="optional"/>
+ <xs:attribute name="metaKey" type="metaKeyEnumType" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="Mouse" type="MouseType" abstract="false" final="#all"
+ substitutionGroup="AbstractInputDeviceGroup"/>
+ <xs:complexType name="MouseType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractInputDeviceType">
+ <xs:attribute name="button" type="mouseButtonType" />
+ <xs:attribute name="state" type="mouseButtonStateEnumType" />
+ <xs:attribute name="metaKey" type="metaKeyEnumType" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="AbstractActionObjectGroup" type="AbstractActionObjectType" abstract="true"/>
+ <xs:complexType name="AbstractActionObjectType" abstract="true">
+ <xs:attribute name="id" type="xs:ID" use="optional"> </xs:attribute>
+ <xs:attribute name="target" type="xs:string" use="optional"> </xs:attribute>
+ <xs:attribute name="origin" type="xs:string" use="optional"> </xs:attribute>
+ </xs:complexType>
+
+ <xs:element name="Add" type="AbstractActionObjectContainerType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="Remove" type="AbstractActionObjectContainerType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="Set" type="AbstractActionObjectContainerType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="Get" type="AbstractActionObjectContainerType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="FlyTo" type="AbstractActionObjectFlyToType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="Bind" type="BindType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="Unbind" type="BindType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="UnbindAll" type="BindType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+ <xs:element name="SendMessage" type="SendMessageType" abstract="false" final="#all"
+ substitutionGroup="AbstractActionObjectGroup"/>
+
+ <xs:complexType name="AbstractActionObjectContainerType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractActionObjectType">
+ <xs:sequence>
+ <xs:element ref="AbstractObjectGroup" minOccurs="0" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="BindType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractActionObjectType">
+ <xs:sequence>
+ <xs:element ref="AbstractInputDeviceGroup" minOccurs="0" maxOccurs="1"></xs:element>
+ <xs:element ref="AbstractActionObjectGroup" minOccurs="0" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="SendMessageType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractActionObjectType">
+ <xs:sequence>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="AbstractActionObjectFlyToType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractActionObjectType">
+ <xs:sequence>
+ <xs:element ref="Camera" minOccurs="0" maxOccurs="1"></xs:element>
+ <xs:element ref="LookAt" minOccurs="0" maxOccurs="1"></xs:element>
+ <xs:element ref="address" minOccurs="0" maxOccurs="1"></xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Message" type="MessageType"/>
+ <xs:complexType name="MessageType" final="#all">
+ <xs:sequence>
+ <xs:element ref="AbstractActionObjectGroup" minOccurs="0" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="optional"/>
+ </xs:complexType>
+
+ <xs:element name="Identity" type="IdentityType" abstract="false" substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="IdentityType">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType">
+ <xs:sequence>
+ <xs:element name="username" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="password" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="domain" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="AbstractExpireTimeGroup" type="AbstractExpireTime" abstract="true"
+ substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="AbstractExpireTime">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType"/>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="ExpireDuration" type="ExpireDurationType" abstract="false"
+ substitutionGroup="AbstractExpireTimeGroup"/>
+ <xs:complexType name="ExpireDurationType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractExpireTime">
+ <xs:attribute name="value" type="xs:double"></xs:attribute>
+ <xs:attribute name="unit" type="timeUnitEnumType"></xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="AbstractGeometryGroup" type="AbstractGeometryType" abstract="true"
+ substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="AbstractGeometryType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType"/>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="coordinates" type="coordinatesType"/>
+ <xs:simpleType name="coordinatesType">
+ <xs:list itemType="xs:string"/>
+ </xs:simpleType>
+
+ <xs:element name="altitudeModeGroup" abstract="false"/>
+ <xs:element name="altitudeMode" type="altitudeModeEnumType" default="clampToGround"
+ substitutionGroup="altitudeModeGroup"/>
+
+ <xs:element name="PointModel" type="PointModeType" substitutionGroup="AbstractGeometryGroup"/>
+ <xs:complexType name="PointModeType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractGeometryType">
+ <xs:sequence>
+ <xs:element ref="Link"/>
+ <xs:element ref="longitude" minOccurs="0"/>
+ <xs:element ref="latitude" minOccurs="0"/>
+ <xs:element ref="altitude" minOccurs="0"/>
+ <xs:element ref="heading" minOccurs="0"/>
+ <xs:element ref="pitch" minOccurs="0"/>
+ <xs:element ref="roll" minOccurs="0"/>
+ <xs:element ref="altitudeMode" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Point" type="PointType" substitutionGroup="AbstractGeometryGroup"/>
+ <xs:complexType name="PointType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractGeometryType">
+ <xs:sequence>
+ <xs:element ref="extrude" minOccurs="0" maxOccurs="1"/>
+ <xs:element ref="altitudeMode" minOccurs="0" maxOccurs="1"/>
+ <xs:element ref="coordinates" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="AbstractViewGroup" type="AbstractViewType" abstract="true"
+ substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="AbstractViewType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType"/>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="LookAt" type="LookAtType"
+ substitutionGroup="AbstractViewGroup"/>
+ <xs:complexType name="LookAtType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractViewType">
+ <xs:sequence>
+ <xs:element ref="longitude" minOccurs="0"></xs:element>
+ <xs:element ref="latitude" minOccurs="0"></xs:element>
+ <xs:element ref="altitude" minOccurs="0"></xs:element>
+ <xs:element ref="heading" minOccurs="0"/>
+ <xs:element ref="pitch" minOccurs="0"/>
+ <xs:element ref="roll" minOccurs="0"/>
+ <xs:element ref="altitudeModeGroup" minOccurs="0"/>
+ <xs:element ref="range" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute ref="vref"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Camera" type="CameraType" abstract="false"
+ substitutionGroup="AbstractViewGroup"/>
+ <xs:complexType name="CameraType">
+ <xs:complexContent>
+ <xs:extension base="AbstractViewType">
+ <xs:sequence>
+ <xs:element ref="longitude" minOccurs="0"></xs:element>
+ <xs:element ref="latitude" minOccurs="0"></xs:element>
+ <xs:element ref="altitude" minOccurs="0"></xs:element>
+ <xs:element ref="heading" minOccurs="0"/>
+ <xs:element ref="pitch" minOccurs="0"/>
+ <xs:element ref="roll" minOccurs="0"/>
+ <xs:element ref="altitudeModeGroup" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute ref="vref"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="AbstractFeatureGroup" type="AbstractFeatureType" abstract="true"
+ substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="AbstractFeatureType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractObjectType">
+ <xs:sequence>
+ <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"> </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"> </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="AbstractWorldFeatureGroup" type="AbstractWorldFeatureType" abstract="true"
+ substitutionGroup="AbstractFeatureGroup"/>
+ <xs:complexType name="AbstractWorldFeatureType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractFeatureType">
+ <xs:sequence>
+ <xs:element ref="LookAt" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="AbstractScreenFeatureGroup" type="AbstractScreenFeatureType" abstract="true"
+ substitutionGroup="AbstractFeatureGroup"/>
+ <xs:complexType name="AbstractScreenFeatureType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractFeatureType"> </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Image" type="ImageType" substitutionGroup="AbstractFeatureGroup"/>
+ <xs:complexType name="ImageType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractWorldFeatureType">
+ <xs:sequence>
+ <xs:element ref="filename" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="ImageGroup" type="ImageGroupType" substitutionGroup="AbstractContainerGroup"/>
+ <xs:complexType name="ImageGroupType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractContainerType">
+ <xs:sequence>
+ <xs:element ref="Image" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="Placemark" type="PlacemarkType" substitutionGroup="AbstractWorldFeatureGroup"/>
+ <xs:complexType name="PlacemarkType" final="#all">
+ <xs:complexContent>
+ <xs:extension base="AbstractWorldFeatureType">
+ <xs:sequence>
+ <xs:element ref="AbstractExpireTimeGroup" minOccurs="0" maxOccurs="1"/>
+ <xs:element ref="AbstractGeometryGroup" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="AbstractContainerGroup" type="AbstractContainerType" abstract="true"
+ substitutionGroup="AbstractFeatureGroup"/>
+ <xs:complexType name="AbstractContainerType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="AbstractFeatureType"> </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="Group" type="GroupType" abstract="false"
+ substitutionGroup="AbstractFeatureGroup"/>
+ <xs:complexType name="GroupType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractContainerType">
+ <xs:sequence>
+ <xs:element ref="AbstractFeatureGroup" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ <xs:attribute ref="groupType" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name = "Object" type="ObjectType" abstract="false" substitutionGroup="AbstractObjectGroup"/>
+ <xs:complexType name="ObjectType" abstract="false">
+ <xs:complexContent>
+ <xs:extension base="AbstractContainerType">
+ <xs:sequence>
+ <xs:element ref="AbstractObjectGroup" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="objectType" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+</xs:schema>
+
diff --git a/ossimPlanet/src/GNUmakefile b/ossimPlanet/src/GNUmakefile
new file mode 100644
index 0000000..8d65fea
--- /dev/null
+++ b/ossimPlanet/src/GNUmakefile
@@ -0,0 +1,7 @@
+TOPDIR = ..
+include $(TOPDIR)/Make/makedefs
+include $(TOPDIR)/Make/makedirdefs
+
+DIRS = $(SRC_DIRS)
+
+include $(TOPDIR)/Make/makedirrules
diff --git a/ossimPlanet/src/ossimPlanet/GNUmakefile b/ossimPlanet/src/ossimPlanet/GNUmakefile
new file mode 100644
index 0000000..14efa34
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/GNUmakefile
@@ -0,0 +1,144 @@
+TOPDIR= ../..
+include $(TOPDIR)/Make/makedefs
+
+CXXFILES = \
+iochannel.cpp \
+mkUtils.cpp\
+netBuffer.cpp\
+netChannel.cpp\
+netChat.cpp\
+netMessage.cpp\
+netMonitor.cpp\
+netSocket.cpp\
+ossimPlanet.cpp\
+ossimPlanetAction.cpp\
+ossimPlanetActionReceiver.cpp\
+ossimPlanetActionRouter.cpp\
+ossimPlanetAnimationPath.cpp \
+ossimPlanetAnimatedPointModel.cpp \
+ossimPlanetAnnotationLayer.cpp\
+ossimPlanetAnnotationLayerNode.cpp\
+ossimPlanetApi.cpp\
+ossimPlanetArchive.cpp\
+ossimPlanetArchiveMapping.cpp\
+ossimPlanetBillboardIcon.cpp\
+ossimPlanetBoundingBox.cpp \
+ossimPlanetCache.cpp \
+ossimPlanetCacheTextureLayer.cpp \
+ossimPlanetClientThread.cpp \
+ossimPlanetCloudLayer.cpp \
+ossimPlanetCompass.cpp \
+ossimPlanetCubeGrid.cpp \
+ossimPlanetDatabasePager.cpp \
+ossimPlanetDestinationCommandAction.cpp \
+ossimPlanetDtedElevationDatabase.cpp \
+ossimPlanetElevationDatabase.cpp \
+ossimPlanetElevationDatabaseGroup.cpp \
+ossimPlanetElevationGrid.cpp \
+ossimPlanetElevationFactory.cpp \
+ossimPlanetElevationRegistry.cpp \
+ossimPlanetEphemeris.cpp \
+ossimPlanetFadeText.cpp \
+ossimPlanetGeneralRasterElevationDatabase.cpp \
+ossimPlanetGeocoder.cpp \
+ossimPlanetGridUtility.cpp \
+ossimPlanetGrid.cpp \
+ossimPlanetIconGeom.cpp \
+ossimPlanetId.cpp \
+ossimPlanetIdManager.cpp \
+ossimPlanetImage.cpp \
+ossimPlanetInteractionController.cpp \
+ossimPlanetIoRoutableMessageHandler.cpp \
+ossimPlanetIoSocket.cpp \
+ossimPlanetIoSocketServerChannel.cpp \
+ossimPlanetIoThread.cpp \
+ossimPlanetJpegImage.cpp \
+ossimPlanetKml.cpp \
+ossimPlanetKmlLayer.cpp \
+ossimPlanetKmlLayerNode.cpp \
+ossimPlanetKmlNetworkLinkNode.cpp \
+ossimPlanetKmlPlacemarkNode.cpp \
+ossimPlanetKmlScreenOverlayNode.cpp \
+ossimPlanetLabelGeom.cpp \
+ossimPlanetLand.cpp \
+ossimPlanetLandCache.cpp \
+ossimPlanetLandCullCallback.cpp \
+ossimPlanetLandReaderWriter.cpp \
+ossimPlanetLatLonHud.cpp \
+ossimPlanetLayer.cpp \
+ossimPlanetLayerFactory.cpp \
+ossimPlanetLayerRegistry.cpp \
+ossimPlanetLookAt.cpp \
+ossimPlanetLsrSpaceTransform.cpp \
+ossimPlanetManipulator.cpp \
+ossimPlanetNavigator.cpp \
+ossimPlanetNode.cpp \
+ossimPlanetNodeFactory.cpp \
+ossimPlanetNodeRegistry.cpp \
+ossimPlanetOperation.cpp \
+ossimPlanetOssimElevationDatabase.cpp \
+ossimPlanetOssimImage.cpp \
+ossimPlanetOssimImageLayer.cpp \
+ossimPlanetPagedLandLod.cpp \
+ossimPlanetPlaneGrid.cpp \
+ossimPlanetPointModel.cpp \
+ossimPlanetViewer.cpp\
+ossimPlanetSceneView.cpp \
+ossimPlanetServerThread.cpp \
+ossimPlanetShaderProgramSetup.cpp \
+ossimPlanetSocketNetworkConnection.cpp \
+ossimPlanetSousaLayer.cpp \
+ossimPlanetSrtmElevationDatabase.cpp \
+ossimPlanetStandardTextureLayerFactory.cpp \
+ossimPlanetTerrain.cpp \
+ossimPlanetTerrainGeometryTechnique.cpp \
+ossimPlanetTerrainLayer.cpp \
+ossimPlanetTerrainTechnique.cpp \
+ossimPlanetTerrainTile.cpp \
+ossimPlanetTexture2D.cpp \
+ossimPlanetTextureLayer.cpp \
+ossimPlanetTextureLayerGroup.cpp \
+ossimPlanetTextureLayerRegistry.cpp \
+ossimPlanetThread.cpp \
+ossimPlanetThreadImp.cpp \
+ossimPlanetThreadPool.cpp \
+ossimPlanetTileRequest.cpp \
+ossimPlanetUtility.cpp \
+ossimPlanetVideoLayer.cpp \
+ossimPlanetViewMatrixBuilder.cpp \
+ossimPlanetVisitors.cpp \
+ossimPlanetWmsClient.cpp \
+ossimPlanetWmsImageLayer.cpp \
+ossimPlanetXmlAction.cpp \
+ossimPlanetYahooGeocoder.cpp \
+sg_file.cpp \
+sg_socket.cpp \
+sg_socket_udp.cpp \
+ul.cpp \
+ulClock.cpp \
+ulError.cpp \
+ulLinkedList.cpp \
+ulList.cpp \
+ulRTTI.cpp
+
+CFILES = \
+ioapi.c \
+unzip.c \
+zip.c
+
+ifneq ("$(OSSIMPLANET_ENABLE_PREDATOR)", "no")
+CXXFILES+=ossimPlanetPredatorVideoLayerNode.cpp
+endif
+
+ifeq ($(OS),MINGW)
+CFILES += iowin32.c
+endif
+
+DEF += -DOSSIMPLANET_LIBRARY
+
+LIBS += $(OSG_LIBS) $(OSSIM_LIBS) $(OTHER_LIBS)
+
+TARGET_BASENAME = ossimPlanet
+LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT)
+
+include $(TOPDIR)/Make/makerules
diff --git a/ossimPlanet/src/ossimPlanet/crypt.h b/ossimPlanet/src/ossimPlanet/crypt.h
new file mode 100644
index 0000000..622f4bc
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/crypt.h
@@ -0,0 +1,132 @@
+/* crypt.h -- base code for crypt/uncrypt ZIPfile
+
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This code is a modified version of crypting code in Infozip distribution
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ If you don't need crypting in your application, just define symbols
+ NOCRYPT and NOUNCRYPT.
+
+ This code support the "Traditional PKWARE Encryption".
+
+ The new AES encryption added on Zip format by Winzip (see the page
+ http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
+ Encryption is not supported.
+*/
+
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+{
+ unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
+ * unpredictable manner on 16-bit systems; not a problem
+ * with any known compiler so far, though */
+
+ temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
+ return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+{
+ (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
+ (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+ (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+ {
+ register int keyshift = (int)((*(pkeys+1)) >> 24);
+ (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+ }
+ return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+{
+ *(pkeys+0) = 305419896L;
+ *(pkeys+1) = 591751049L;
+ *(pkeys+2) = 878082192L;
+ while (*passwd != '\0') {
+ update_keys(pkeys,pcrc_32_tab,(int)*passwd);
+ passwd++;
+ }
+}
+
+#define zdecode(pkeys,pcrc_32_tab,c) \
+ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
+
+#define zencode(pkeys,pcrc_32_tab,c,t) \
+ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+
+#define RAND_HEAD_LEN 12
+ /* "last resort" source for second part of crypt seed pattern */
+# ifndef ZCR_SEED2
+# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
+# endif
+
+static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
+ const char *passwd; /* password string */
+ unsigned char *buf; /* where to write header */
+ int bufSize;
+ unsigned long* pkeys;
+ const unsigned long* pcrc_32_tab;
+ unsigned long crcForCrypting;
+{
+ int n; /* index in random header */
+ int t; /* temporary */
+ int c; /* random byte */
+ unsigned char header[RAND_HEAD_LEN-2]; /* random header */
+ static unsigned calls = 0; /* ensure different random header each time */
+
+ if (bufSize<RAND_HEAD_LEN)
+ return 0;
+
+ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+ * output of rand() to get less predictability, since rand() is
+ * often poorly implemented.
+ */
+ if (++calls == 1)
+ {
+ srand((unsigned)(time(NULL) ^ ZCR_SEED2));
+ }
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ c = (rand() >> 7) & 0xff;
+ header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
+ }
+ /* Encrypt random header (last two bytes is high word of crc) */
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
+ }
+ buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+ buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+ return n;
+}
+
+#endif
diff --git a/ossimPlanet/src/ossimPlanet/ioapi.c b/ossimPlanet/src/ossimPlanet/ioapi.c
new file mode 100644
index 0000000..9626796
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ioapi.c
@@ -0,0 +1,177 @@
+/* ioapi.c -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+#include <ossimPlanet/ioapi.h>
+
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+voidpf ZCALLBACK fopen_file_func OF((
+ voidpf opaque,
+ const char* filename,
+ int mode));
+
+uLong ZCALLBACK fread_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ void* buf,
+ uLong size));
+
+uLong ZCALLBACK fwrite_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ const void* buf,
+ uLong size));
+
+long ZCALLBACK ftell_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+long ZCALLBACK fseek_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ uLong offset,
+ int origin));
+
+int ZCALLBACK fclose_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+int ZCALLBACK ferror_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
+ voidpf opaque;
+ const char* filename;
+ int mode;
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ void* buf;
+ uLong size;
+{
+ uLong ret;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ const void* buf;
+ uLong size;
+{
+ uLong ret;
+ ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+long ZCALLBACK ftell_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ long ret;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
+ voidpf opaque;
+ voidpf stream;
+ uLong offset;
+ int origin;
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ fseek((FILE *)stream, offset, fseek_origin);
+ return ret;
+}
+
+int ZCALLBACK fclose_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+int ZCALLBACK ferror_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/ossimPlanet/src/ossimPlanet/iochannel.cpp b/ossimPlanet/src/ossimPlanet/iochannel.cpp
new file mode 100644
index 0000000..7bd7796
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/iochannel.cpp
@@ -0,0 +1,84 @@
+// iochannel.cxx -- High level IO channel class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: iochannel.cpp 11616 2007-08-15 18:23:33Z gpotts $
+
+
+#include <ossimPlanet/iochannel.h>
+
+
+// constructor
+SGIOChannel::SGIOChannel()
+ :theReadlineDelimiter('\n')
+{
+}
+
+
+// destructor
+SGIOChannel::~SGIOChannel()
+{
+}
+
+
+// dummy configure routine
+bool SGIOChannel::open( const SGProtocolDir /*d*/ ) {
+ return false;
+}
+
+
+// dummy process routine
+int SGIOChannel::read( char * /*buf*/, int /*length*/ ) {
+ return 0;
+}
+
+
+// dummy process routine
+int SGIOChannel::readline( char * /*buf*/, int /*length*/ ) {
+ return 0;
+}
+
+void SGIOChannel::setReadlineDelimiter(char delimiter)
+{
+ theReadlineDelimiter = delimiter;
+}
+
+
+// dummy process routine
+int SGIOChannel::write( const char * /*buf*/, const int /*length*/ ) {
+ return false;
+}
+
+
+// dummy process routine
+int SGIOChannel::writestring( const char * /*str*/ ) {
+ return false;
+}
+
+
+// dummy close routine
+bool SGIOChannel::close() {
+ return false;
+}
+
+
+// dummy eof routine
+bool SGIOChannel::eof() {
+ return false;
+}
diff --git a/ossimPlanet/src/ossimPlanet/iowin32.c b/ossimPlanet/src/ossimPlanet/iowin32.c
new file mode 100644
index 0000000..ab153e8
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/iowin32.c
@@ -0,0 +1,270 @@
+/* iowin32.c -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+ This IO API version uses the Win32 API (for Microsoft Windows)
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <stdlib.h>
+
+#include "zlib.h"
+#include <ossimPlanet/ioapi.h>
+#include <ossimPlanet/iowin32.h>
+
+#ifndef INVALID_HANDLE_VALUE
+#define INVALID_HANDLE_VALUE (0xFFFFFFFF)
+#endif
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+
+voidpf ZCALLBACK win32_open_file_func OF((
+ voidpf opaque,
+ const char* filename,
+ int mode));
+
+uLong ZCALLBACK win32_read_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ void* buf,
+ uLong size));
+
+uLong ZCALLBACK win32_write_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ const void* buf,
+ uLong size));
+
+long ZCALLBACK win32_tell_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+long ZCALLBACK win32_seek_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ uLong offset,
+ int origin));
+
+int ZCALLBACK win32_close_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+int ZCALLBACK win32_error_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+typedef struct
+{
+ HANDLE hf;
+ int error;
+} WIN32FILE_IOWIN;
+
+voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
+ voidpf opaque;
+ const char* filename;
+ int mode;
+{
+ const char* mode_fopen = NULL;
+ DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+ HANDLE hFile = 0;
+ voidpf ret=NULL;
+
+ dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
+
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ {
+ dwDesiredAccess = GENERIC_READ;
+ dwCreationDisposition = OPEN_EXISTING;
+ dwShareMode = FILE_SHARE_READ;
+ }
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ {
+ dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+ dwCreationDisposition = OPEN_EXISTING;
+ }
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ {
+ dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+ dwCreationDisposition = CREATE_ALWAYS;
+ }
+
+ if ((filename!=NULL) && (dwDesiredAccess != 0))
+ hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
+ dwCreationDisposition, dwFlagsAndAttributes, NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ hFile = NULL;
+
+ if (hFile != NULL)
+ {
+ WIN32FILE_IOWIN w32fiow;
+ w32fiow.hf = hFile;
+ w32fiow.error = 0;
+ ret = malloc(sizeof(WIN32FILE_IOWIN));
+ if (ret==NULL)
+ CloseHandle(hFile);
+ else *((WIN32FILE_IOWIN*)ret) = w32fiow;
+ }
+ return ret;
+}
+
+
+uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ void* buf;
+ uLong size;
+{
+ uLong ret=0;
+ HANDLE hFile = NULL;
+ if (stream!=NULL)
+ hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+ if (hFile != NULL)
+ if (!ReadFile(hFile, buf, size, &ret, NULL))
+ {
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_HANDLE_EOF)
+ dwErr = 0;
+ ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+ }
+
+ return ret;
+}
+
+
+uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ const void* buf;
+ uLong size;
+{
+ uLong ret=0;
+ HANDLE hFile = NULL;
+ if (stream!=NULL)
+ hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+
+ if (hFile !=NULL)
+ if (!WriteFile(hFile, buf, size, &ret, NULL))
+ {
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_HANDLE_EOF)
+ dwErr = 0;
+ ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+ }
+
+ return ret;
+}
+
+long ZCALLBACK win32_tell_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ long ret=-1;
+ HANDLE hFile = NULL;
+ if (stream!=NULL)
+ hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+ if (hFile != NULL)
+ {
+ DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+ if (dwSet == INVALID_SET_FILE_POINTER)
+ {
+ DWORD dwErr = GetLastError();
+ ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+ ret = -1;
+ }
+ else
+ ret=(long)dwSet;
+ }
+ return ret;
+}
+
+long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
+ voidpf opaque;
+ voidpf stream;
+ uLong offset;
+ int origin;
+{
+ DWORD dwMoveMethod=0xFFFFFFFF;
+ HANDLE hFile = NULL;
+
+ long ret=-1;
+ if (stream!=NULL)
+ hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ dwMoveMethod = FILE_CURRENT;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ dwMoveMethod = FILE_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ dwMoveMethod = FILE_BEGIN;
+ break;
+ default: return -1;
+ }
+
+ if (hFile != NULL)
+ {
+ DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
+ if (dwSet == INVALID_SET_FILE_POINTER)
+ {
+ DWORD dwErr = GetLastError();
+ ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+ ret = -1;
+ }
+ else
+ ret=0;
+ }
+ return ret;
+}
+
+int ZCALLBACK win32_close_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret=-1;
+
+ if (stream!=NULL)
+ {
+ HANDLE hFile;
+ hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+ if (hFile != NULL)
+ {
+ CloseHandle(hFile);
+ ret=0;
+ }
+ free(stream);
+ }
+ return ret;
+}
+
+int ZCALLBACK win32_error_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret=-1;
+ if (stream!=NULL)
+ {
+ ret = ((WIN32FILE_IOWIN*)stream) -> error;
+ }
+ return ret;
+}
+
+void fill_win32_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = win32_open_file_func;
+ pzlib_filefunc_def->zread_file = win32_read_file_func;
+ pzlib_filefunc_def->zwrite_file = win32_write_file_func;
+ pzlib_filefunc_def->ztell_file = win32_tell_file_func;
+ pzlib_filefunc_def->zseek_file = win32_seek_file_func;
+ pzlib_filefunc_def->zclose_file = win32_close_file_func;
+ pzlib_filefunc_def->zerror_file = win32_error_file_func;
+ pzlib_filefunc_def->opaque=NULL;
+}
diff --git a/ossimPlanet/src/ossimPlanet/mkUtils.cpp b/ossimPlanet/src/ossimPlanet/mkUtils.cpp
new file mode 100644
index 0000000..c0c92eb
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/mkUtils.cpp
@@ -0,0 +1,471 @@
+#include <ossimPlanet/mkUtils.h>
+#include <ossim/base/ossimCommon.h>
+#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimCommon.h>
+#include <iostream>
+#include <stack>
+
+std::istream& mkUtils::planetSkipws(std::istream& in)
+{
+ int c = in.peek();
+ while(!in.fail()&&
+ ((c == ' ') ||
+ (c == '\t') ||
+ (c == '\n')||
+ (c == '\r')))
+ {
+ in.ignore(1);
+ c = in.peek();
+ }
+
+ return in;
+}
+
+bool mkUtils::writeOsgObjectToStream(std::ostream& out, const osg::Object* node, const std::string& extension)
+{
+ osg::ref_ptr<osgDB::ReaderWriter> writer = osgDB::Registry::instance()->getReaderWriterForExtension(extension);
+ return writer.valid() ? writer->writeObject(*node, out).success() : false;
+}
+
+bool mkUtils::isDouble(const std::string& s)
+{
+ char* end;
+ const char* start = s.c_str();
+ strtod(start, &end);
+ return start != end;
+}
+
+bool mkUtils::isInt(const std::string& s)
+{
+ char* end;
+ const char* start = s.c_str();
+ strtoul(start, &end, 0);
+ return start != end;
+}
+
+double mkUtils::asDouble(const std::string& s)
+{
+ char* end;
+ const char* start = s.c_str();
+ double x = strtod(start, &end);
+ return (start != end) ? x : ossim::nan();
+}
+
+bool mkUtils::hasSuffix(const std::string& s, const std::string& suffix)
+{
+ std::string::size_type sSize = s.size();
+ std::string::size_type suffixSize = suffix.size();
+ return (suffixSize <= sSize) ? suffix == s.substr(sSize - suffixSize, suffixSize) : false;
+}
+
+ossim_int64 mkUtils::factorial(int n)
+{
+ // only factorials for small n can fit in int64 so just use a 168 byte lookup table.
+
+ const int tableLength = 21;
+ if((n < 0) || (n > tableLength)) return 0;
+// assert(n >= 0 && n < tableLength);
+
+ static const ossim_int64 table[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
+ 39916800, 479001600, 6227020800LL, 87178291200LL, 1307674368000LL, 20922789888000LL,
+ 355687428096000LL, 6402373705728000LL, 121645100408832000LL, 2432902008176640000LL };
+ // XXX add this back in later: static_check(tableLength == sizeof(table)/sizeof(table[0]), tableLength_must_equal_actual_table_length);
+
+ return table[n];
+}
+
+void mkUtils::lexBraceQuotedTokens(const std::string& str, unsigned int startIdx, const char* whitespace, std::vector<std::string>* tokens, bool* unbalancedBraces)
+{
+ ossim::lexQuotedTokens(str, startIdx, whitespace, "{}", *tokens, *unbalancedBraces);
+#if 0
+ if(!whitespace||!tokens||!unbalancedBraces) return;
+// assert(whitespace != NULL);
+// assert(tokens != NULL);
+// assert(unbalancedBraces != NULL);
+
+ const char openQuote('{'), closeQuote('}');
+
+ tokens->clear();
+ *unbalancedBraces = false;
+
+ unsigned int endIdx;
+ while (startIdx < str.length())
+ {
+ if (str[startIdx] == openQuote)
+ {
+ int openBraceCount = 1;
+
+ if (startIdx+1 < str.length())
+ {
+ startIdx++;
+ if (str[startIdx] != closeQuote)
+ {
+ endIdx = startIdx+1;
+ while (endIdx < str.length() && openBraceCount > 0)
+ {
+ if (str[endIdx] == openQuote)
+ openBraceCount++;
+ else if (str[endIdx] == closeQuote)
+ openBraceCount--;
+ endIdx++;
+ }
+ }
+ else
+ {
+ openBraceCount = 0;
+ startIdx++;
+ endIdx = startIdx+1;
+ }
+ }
+
+ if (openBraceCount == 0)
+ {
+ tokens->push_back(str.substr(startIdx, endIdx-1-startIdx));
+ }
+ else
+ {
+ *unbalancedBraces = true;
+ endIdx = str.length();
+ }
+
+ }
+ else if (str[startIdx] == closeQuote)
+ {
+ *unbalancedBraces = true;
+ endIdx = str.length();
+
+ }
+ else
+ {
+ endIdx = str.find_first_of(whitespace, startIdx);
+ tokens->push_back(str.substr(startIdx, endIdx-startIdx));
+ }
+
+ startIdx = str.find_first_not_of(whitespace, endIdx);
+ }
+#endif
+}
+
+void mkUtils::hprToQuat(osg::Quat& quat, const osg::Vec3d& hpr)
+{
+// const double yaw(osg::DegreesToRadians(hpr[1]));
+// const double pitch(osg::DegreesToRadians(hpr[2]));
+// const double roll(osg::DegreesToRadians(-hpr[0]));
+ const double yaw(osg::DegreesToRadians(-hpr[0]));
+ const double pitch(osg::DegreesToRadians(hpr[1]));
+ const double roll(osg::DegreesToRadians(hpr[2]));
+ const double cy ( cos ( yaw * 0.5 ) );
+ const double cp ( cos ( pitch * 0.5 ) );
+ const double cr ( cos ( roll * 0.5 ) );
+ const double sy ( sin ( yaw * 0.5 ) );
+ const double sp ( sin ( pitch * 0.5 ) );
+ const double sr ( sin ( roll * 0.5 ) );
+
+ const double qw ( cy*cp*cr + sy*sp*sr );
+ const double qx ( sy*cp*cr - cy*sp*sr );
+ const double qy ( cy*sp*cr + sy*cp*sr );
+ const double qz ( cy*cp*sr - sy*sp*cr );
+
+ quat.set ( qx, qy, qz, qw );
+}
+
+void mkUtils::quatToHpr(osg::Vec3d& hpr, const osg::Quat& quat)
+{
+ // From the reference material the h p r is about
+ // Y, Z, and X
+ // our LSR axiz says Z, X, Y
+ const double q0 ( quat[3] );
+ const double q1 ( quat[0] );
+ const double q2 ( quat[1] );
+ const double q3 ( quat[2] );
+ const double sqx(q1*q1);
+ const double sqy(q2*q2);
+ const double sqz(q3*q3);
+ const double sqw(q0*q0);
+
+ double h = atan2(2.0 * (q1*q2 + q3*q0),(sqx - sqy - sqz + sqw));
+ double p = atan2(2.0 * (q2*q3 + q1*q0),(-sqx - sqy + sqz + sqw));
+ double r = asin(-2.0 * (q1*q3 - q2*q0)/(sqx + sqy + sqz + sqw));
+// const double h(atan2 ( 2 * (q2*q3 + q0*q1), (q0*q0 - q1*q1 - q2*q2 + q3*q3)));
+// double p(asin ( -2 * (q1*q3 - q0*q2)));
+// double r(atan2 ( 2 * (q1*q2 + q0*q3), (q0*q0 + q1*q1 - q2*q2 - q3*q3)));
+ // hpr = osg::Vec3d(osg::RadiansToDegrees(-r),
+ // osg::RadiansToDegrees(h),
+ // osg::RadiansToDegrees(p));
+ hpr = osg::Vec3d(osg::RadiansToDegrees(-h),
+ osg::RadiansToDegrees(p),
+ osg::RadiansToDegrees(r));
+}
+
+bool mkUtils::matrixToHpr( osg::Vec3d& hpr,
+ const osg::Matrixd& rotation )
+{
+// std::cout << "HEADING = " << ossim::radiansToDegrees(atan(rotation(0,1)/rotation(0,0))) << std::endl;
+// std::cout << "PITCH = " << ossim::radiansToDegrees(asin(-rotation(0,2))) << std::endl;
+// std::cout << "ROLL = " << ossim::radiansToDegrees(atan(rotation(1,2)/rotation(2,2))) << std::endl;
+
+ osg::Quat q;
+
+ q.set(rotation);
+
+ quatToHpr(hpr, q);
+
+ return true;
+}
+
+bool mkUtils::matrixToHpr( osg::Vec3d& hpr,
+ const osg::Matrixd& lsrMatrix,
+ const osg::Matrixd& rotationalMatrix)
+{
+ bool result = false;
+ osg::Matrixd invertLsr;
+
+ hpr[0] = 0.0;
+ hpr[1] = 0.0;
+ hpr[2] = 0.0;
+ osg::Matrixd m(lsrMatrix(0,0), lsrMatrix(0, 1), lsrMatrix(0,2), 0.0,
+ lsrMatrix(1,0), lsrMatrix(1, 1), lsrMatrix(1,2), 0.0,
+ lsrMatrix(2,0), lsrMatrix(2, 1), lsrMatrix(2,2), 0.0,
+ 0.0,0.0,0.0, 1.0);
+ if(invertLsr.invert(m))
+ {
+ result = matrixToHpr(hpr, rotationalMatrix*invertLsr);
+ if(std::abs(hpr[0]) < FLT_EPSILON)
+ {
+ hpr[0] = 0.0;
+ }
+ if(std::abs(hpr[1]) < FLT_EPSILON)
+ {
+ hpr[1] = 0.0;
+ }
+ if(std::abs(hpr[2]) < FLT_EPSILON)
+ {
+ hpr[2] = 0.0;
+ }
+ }
+ return result;
+}
+
+bool mkUtils::extractObjectAndArg(std::string& resultObject,
+ std::string& resultArg,
+ const std::string& inputValue,
+ const char quotes[2])
+{
+ const char openQuote(quotes[0]), closeQuote(quotes[1]);
+ std::vector<std::string> tokens;
+ bool unbalancedQuotes=false;
+ ossim_uint32 end = 1;
+ ossim_uint32 start=0;
+ ossim_uint32 totalOpenQuoteCount = 0;
+ const char* whitespace = " \t\n\r";
+ // while (start < inputValue.length() && start >= 0)
+ start = inputValue.find_first_not_of(whitespace, start);
+ end = start + 1;
+ if(inputValue[start] != openQuote)
+ {
+ while (start < inputValue.length())
+ {
+ if (inputValue[start] == openQuote)
+ {
+ int openBraceCount = 1;
+ ++totalOpenQuoteCount;
+ if (start+1 < inputValue.length())
+ {
+ ++start;
+ // skip white space since this is the object portion and need te start of the first character
+ //
+ start = inputValue.find_first_not_of(whitespace, start);
+ if (inputValue[start] != closeQuote)
+ {
+ end = start+1;
+ while (static_cast<ossim_uint32>(end) < inputValue.length() &&
+ openBraceCount > 0)
+ {
+ if (inputValue[end] == openQuote)
+ {
+ openBraceCount++;
+ ++totalOpenQuoteCount;
+ }
+ else if (inputValue[end] == closeQuote)
+ openBraceCount--;
+ end++;
+ }
+ }
+ else
+ {
+ openBraceCount = 0;
+ start++;
+ end = start+1;
+ }
+ }
+
+ if (openBraceCount == 0)
+ {
+ tokens.push_back(inputValue.substr(start, end-1-start));
+ }
+ else
+ {
+ unbalancedQuotes = true;
+ end = inputValue.length();
+ }
+
+ }
+ else if (inputValue[start] == closeQuote)
+ {
+ unbalancedQuotes = true;
+ end = inputValue.length();
+
+ }
+ else
+ {
+ end = inputValue.find_first_of(whitespace, start);
+ tokens.push_back(inputValue.substr(start, end-start));
+ }
+
+ start = inputValue.find_first_not_of(whitespace, end);
+ }
+ }
+ else
+ {
+ end = inputValue.find_first_of(whitespace, start);
+ tokens.push_back(inputValue.substr(start, end-start));
+ tokens.push_back(inputValue.substr(end, inputValue.size()));
+ }
+ if(unbalancedQuotes) return false;
+ if(tokens.size() < 2) return false;
+ bool requoteArg = totalOpenQuoteCount >0;
+ resultObject = tokens[0];
+ resultArg = "";
+ ossim_uint32 maxSize = tokens.size()-1;
+ ossim_uint32 idx = 0;
+ for(idx =1; idx < maxSize; ++idx)
+ {
+ if(requoteArg)
+ {
+ resultArg += (quotes[0] + tokens[idx]+quotes[1]);
+ }
+ else
+ {
+ resultArg += tokens[idx];
+ }
+ resultArg += " ";
+ }
+ if(requoteArg)
+ {
+ resultArg += (quotes[0] + tokens[idx]+quotes[1]);
+ }
+ else
+ {
+ resultArg += tokens[idx];
+ }
+
+ return true;
+}
+
+ossimRefPtr<ossimXmlNode> mkUtils::newNodeFromObjectMessageRoute(const ossimString& v,
+ const char quotes[2])
+{
+ std::istringstream in(v);
+ const char openQuote = quotes[0];
+ const char closeQuote = quotes[1];
+ std::stack<ossimRefPtr<ossimXmlNode> > xmlStack;
+ ossimRefPtr<ossimXmlNode> current;
+ in >> mkUtils::planetSkipws;
+ if(!in.good()) return current;
+ current = new ossimXmlNode;
+ xmlStack.push(current.get());
+
+ if(in.peek() == openQuote)
+ {
+ in.ignore();
+ }
+ ossimString name;
+ ossimString value;
+ while(in.good()&&!xmlStack.empty())
+ {
+ in>>mkUtils::planetSkipws;
+ if(in.peek() == openQuote)
+ {
+ // create a new xml node
+ // add it to current and skip white space to parse out the name
+ //
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ name = "";
+ value = "";
+ current->addChildNode(node.get());
+ xmlStack.push(node.get());
+ current = node;
+ in.ignore();
+ }
+ else if(in.peek() == closeQuote)
+ {
+ xmlStack.pop();
+ if(xmlStack.size() > 0)
+ {
+ current = xmlStack.top();
+ }
+ in.ignore();
+ }
+ else
+ {
+ if(name.empty())
+ {
+ // read object name
+ //
+ while(in.good()&&(in.peek()!=' ')&&(in.peek()!=openQuote)&&(in.peek()!=closeQuote))
+ {
+ name += (char)in.get();
+ }
+ // on last pop there is a possibility that the name will be parsed to empty so don't overwrite.
+ // we are basically done at this point and the main loop should kick out
+ //
+ if(!name.empty())
+ {
+ current->setTag(name);
+ }
+ }
+ else if(value.empty())
+ {
+ while(in.good()&&(in.peek()!=closeQuote))
+ {
+ value += (char)in.get();
+ }
+ current->setText(value);
+ // reset name and value;
+ name = "";
+ value = "";
+ }
+ }
+ }
+ // check for error
+ //
+ if(!in.good())
+ {
+ if(xmlStack.size() != 1)
+ {
+ current = 0;
+ }
+ }
+
+ return current;
+}
+
+ossimRefPtr<ossimXmlNode> mkUtils::newNodeFromObjectMessageRoute(const ossimString& receiverPath,
+ const ossimString& command,
+ const ossimString& v,
+ const char quotes[2])
+{
+ ossimRefPtr<ossimXmlNode> objectDefinition = newNodeFromObjectMessageRoute(v, quotes);
+ ossimRefPtr<ossimXmlNode> result;
+ if(objectDefinition.valid())
+ {
+ result = new ossimXmlNode;
+ result->setTag("Message");
+ result->addAttribute("receiver", receiverPath);
+ result->addAttribute("command", receiverPath);
+
+ }
+ return result.get();
+}
diff --git a/ossimPlanet/src/ossimPlanet/netBuffer.cpp b/ossimPlanet/src/ossimPlanet/netBuffer.cpp
new file mode 100644
index 0000000..0885939
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/netBuffer.cpp
@@ -0,0 +1,69 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netBuffer.cxx 1568 2002-09-02 06:05:49Z sjbaker $
+*/
+
+#include <ossimPlanet/netBuffer.h>
+
+void
+netBufferChannel::handleRead (void)
+{
+ int max_read = in_buffer.getMaxLength() - in_buffer.getLength() ;
+ if (max_read)
+ {
+ char* data = in_buffer.getData() + in_buffer.getLength() ;
+ int num_read = recv (data, max_read) ;
+ if (num_read > 0)
+ {
+ in_buffer.append (num_read) ;
+ //ulSetError ( UL_DEBUG, "netBufferChannel: %d read", num_read ) ;
+ }
+ }
+ if (in_buffer.getLength())
+ {
+ handleBufferRead (in_buffer);
+ }
+}
+
+void
+netBufferChannel::handleWrite (void)
+{
+ if (out_buffer.getLength())
+ {
+ if (isConnected())
+ {
+ int length = out_buffer.getLength() ;
+ if (length>512)
+ length=512;
+ int num_sent = netChannel::send (
+ out_buffer.getData(), length);
+ if (num_sent > 0)
+ {
+ out_buffer.remove (0, num_sent);
+ //ulSetError ( UL_DEBUG, "netBufferChannel: %d sent", num_sent ) ;
+ }
+ }
+ }
+ else if (should_close)
+ {
+ close();
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/netChannel.cpp b/ossimPlanet/src/ossimPlanet/netChannel.cpp
new file mode 100644
index 0000000..677965b
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/netChannel.cpp
@@ -0,0 +1,279 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netChannel.cxx 1906 2004-03-22 19:44:50Z sjbaker $
+*/
+
+// TODO:
+// have all socket-related functions assert that the socket has not
+// been closed. [a read event may close it, and a write event may try
+// to write or something...]
+// Maybe assert valid handle, too?
+
+#include <ossimPlanet/netChannel.h>
+
+static netChannel* channels = 0 ;
+
+netChannel::netChannel ()
+{
+ closed = true ;
+ connected = false ;
+ accepting = false ;
+ write_blocked = false ;
+ should_delete = false ;
+
+ next_channel = channels ;
+ channels = this ;
+}
+
+netChannel::~netChannel ()
+{
+ close();
+
+ netChannel* prev = NULL ;
+
+ for ( netChannel* ch = channels; ch != NULL;
+ ch = ch -> next_channel )
+ {
+ if (ch == this)
+ {
+ ch = ch -> next_channel ;
+ if ( prev != NULL )
+ prev -> next_channel = ch ;
+ else
+ channels = ch ;
+ next_channel = 0 ;
+ break;
+ }
+ prev = ch ;
+ }
+}
+
+void
+netChannel::setHandle (int handle, bool is_connected)
+{
+ close () ;
+ netSocket::setHandle ( handle ) ;
+ connected = is_connected ;
+ //if ( connected ) this->handleConnect();
+ closed = false ;
+}
+
+bool
+netChannel::open (bool streamFlag)
+{
+ close();
+ if (netSocket::open(streamFlag)) {
+ closed = false ;
+ setBlocking ( false ) ;
+ return true ;
+ }
+ return false ;
+}
+
+int
+netChannel::listen ( int backlog )
+{
+ accepting = true ;
+ return netSocket::listen ( backlog ) ;
+}
+
+int
+netChannel::connect ( const char* host, int port )
+{
+ int result = netSocket::connect ( host, port ) ;
+ if (result == 0) {
+ connected = true ;
+ //this->handleConnect();
+ return 0;
+ } else if (isNonBlockingError ()) {
+ return 0;
+ } else {
+ // some other error condition
+ this->handleError (result);
+ close();
+ return -1;
+ }
+}
+
+int
+netChannel::send (const void * buffer, int size, int flags)
+{
+ int result = netSocket::send (buffer, size, flags);
+
+ if (result == (int)size) {
+ // everything was sent
+ write_blocked = false ;
+ return result;
+ } else if (result >= 0) {
+ // not all of it was sent, but no error
+ write_blocked = true ;
+ return result;
+ } else if (isNonBlockingError ()) {
+ write_blocked = true ;
+ return 0;
+ } else {
+ this->handleError (result);
+ close();
+ return -1;
+ }
+
+}
+
+int
+netChannel::recv (void * buffer, int size, int flags)
+{
+ int result = netSocket::recv (buffer, size, flags);
+
+ if (result > 0) {
+ return result;
+ } else if (result == 0) {
+ close();
+ return 0;
+ } else if (isNonBlockingError ()) {
+ return 0;
+ } else {
+ this->handleError (result);
+ close();
+ return -1;
+ }
+}
+
+void
+netChannel::close (void)
+{
+ if ( !closed )
+ {
+ this->handleClose();
+
+ closed = true ;
+ connected = false ;
+ accepting = false ;
+ write_blocked = false ;
+ }
+
+ netSocket::close () ;
+}
+
+void
+netChannel::handleReadEvent (void)
+{
+ if (accepting) {
+ if (!connected) {
+ connected = true ;
+ //this->handleConnect();
+ }
+ this->handleAccept();
+ } else if (!connected) {
+ connected = true ;
+ //this->handleConnect();
+ this->handleRead();
+ } else {
+ this->handleRead();
+ }
+}
+
+void
+netChannel::handleWriteEvent (void)
+{
+ if (!connected) {
+ connected = true ;
+ //this->handleConnect();
+ }
+ write_blocked = false ;
+ this->handleWrite();
+}
+
+bool
+netChannel::poll (unsigned int timeout)
+{
+ if (!channels)
+ return false ;
+
+ enum { MAX_SOCKETS = 256 } ;
+ netSocket* reads [ MAX_SOCKETS+1 ] ;
+ netSocket* writes [ MAX_SOCKETS+1 ] ;
+ netSocket* deletes [ MAX_SOCKETS+1 ] ;
+ int nreads = 0 ;
+ int nwrites = 0 ;
+ int ndeletes = 0 ;
+ int nopen = 0 ;
+ netChannel* ch;
+ for ( ch = channels; ch != NULL; ch = ch -> next_channel )
+ {
+ if ( ch -> should_delete )
+ {
+ assert(ndeletes<MAX_SOCKETS);
+ deletes[ndeletes++] = ch ;
+ }
+ else if ( ! ch -> closed )
+ {
+ nopen++ ;
+ if (ch -> readable()) {
+ assert(nreads<MAX_SOCKETS);
+ reads[nreads++] = ch ;
+ }
+ if (ch -> writable()) {
+ assert(nwrites<MAX_SOCKETS);
+ writes[nwrites++] = ch ;
+ }
+ }
+ }
+ reads[nreads] = NULL ;
+ writes[nwrites] = NULL ;
+ deletes[ndeletes] = NULL ;
+
+ int i ;
+ for ( i=0; deletes[i]; i++ )
+ {
+ ch = (netChannel*)deletes[i];
+ delete ch ;
+ }
+
+ if (!nopen)
+ return false ;
+ if (!nreads && !nwrites)
+ return true ; //hmmm- should we shutdown?
+
+ netSocket::select (reads, writes, timeout) ;
+
+ for ( i=0; reads[i]; i++ )
+ {
+ ch = (netChannel*)reads[i];
+ if ( ! ch -> closed )
+ ch -> handleReadEvent();
+ }
+
+ for ( i=0; writes[i]; i++ )
+ {
+ ch = (netChannel*)writes[i];
+ if ( ! ch -> closed )
+ ch -> handleWriteEvent();
+ }
+
+ return true ;
+}
+
+void
+netChannel::loop (unsigned int timeout)
+{
+ while ( poll (timeout) ) ;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/netChat.cpp b/ossimPlanet/src/ossimPlanet/netChat.cpp
new file mode 100644
index 0000000..804d1db
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/netChat.cpp
@@ -0,0 +1,125 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netChat.cxx 2117 2007-09-13 23:21:09Z fayjf $
+*/
+
+#include <ossimPlanet/netChat.h>
+
+void
+netChat::setTerminator (const char* t)
+{
+ if (terminator) delete[] terminator;
+ terminator = ulStrDup(t);
+}
+
+const char*
+netChat::getTerminator (void)
+{
+ return terminator;
+}
+
+// return the size of the largest prefix of needle at the end
+// of haystack
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+static int
+find_prefix_at_end (const netBuffer& haystack, const char* needle)
+{
+ const char* hd = haystack.getData();
+ int hl = haystack.getLength();
+ int nl = strlen(needle);
+
+ for (int i = MAX (nl-hl, 0); i < nl; i++) {
+ //if (haystack.compare (needle, hl-(nl-i), nl-i) == 0) {
+ if (memcmp(needle, &hd[hl-(nl-i)], nl-i) == 0) {
+ return (nl-i);
+ }
+ }
+ return 0;
+}
+
+static int
+find_terminator (const netBuffer& haystack, const char* needle)
+{
+ if (needle && *needle)
+ {
+ const char* data = haystack.getData();
+ const char* ptr = strstr(data,needle);
+ if (ptr != NULL)
+ return(ptr-data);
+ }
+ return -1;
+}
+
+
+void
+netChat::handleBufferRead (netBuffer& in_buffer)
+{
+ // Continue to search for terminator in in_buffer,
+ // while calling collect_incoming_data. The while loop is
+ // necessary because we might read several data+terminator combos
+ // with a single recv().
+
+ while (in_buffer.getLength()) {
+
+ // special case where we're not using a terminator
+ if (terminator == 0 || *terminator == 0) {
+ collectIncomingData (in_buffer.getData(),in_buffer.getLength());
+ in_buffer.remove ();
+ return;
+ }
+
+ int terminator_len = strlen(terminator);
+
+ int index = find_terminator ( in_buffer, terminator ) ;
+
+ // 3 cases:
+ // 1) end of buffer matches terminator exactly:
+ // collect data, transition
+ // 2) end of buffer matches some prefix:
+ // collect data to the prefix
+ // 3) end of buffer does not match any prefix:
+ // collect data
+
+ if (index != -1) {
+ // we found the terminator
+ collectIncomingData ( in_buffer.getData(), index ) ;
+ in_buffer.remove (0, index + terminator_len);
+ foundTerminator();
+ } else {
+ // check for a prefix of the terminator
+ int num = find_prefix_at_end (in_buffer, terminator);
+ if (num) {
+ int bl = in_buffer.getLength();
+ // we found a prefix, collect up to the prefix
+ collectIncomingData ( in_buffer.getData(), bl - num ) ;
+ in_buffer.remove (0, bl - num);
+ break;
+ } else {
+ // no prefix, collect it all
+ collectIncomingData (in_buffer.getData(), in_buffer.getLength());
+ in_buffer.remove();
+ }
+ }
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/netMessage.cpp b/ossimPlanet/src/ossimPlanet/netMessage.cpp
new file mode 100644
index 0000000..5affa53
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/netMessage.cpp
@@ -0,0 +1,50 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netMessage.cxx 1899 2004-03-21 17:41:07Z sjbaker $
+*/
+
+#include <ossimPlanet/netMessage.h>
+
+
+void
+netMessageChannel::handleBufferRead (netBuffer& in_buffer)
+{
+ int n = in_buffer.getLength () ;
+ while ( n >= 2 )
+ {
+ unsigned short msg_len = *( (unsigned short*)in_buffer.getData() ) ;
+ if ( n >= msg_len )
+ {
+ //we have a complete message; handle it
+ netMessage msg(in_buffer.getData(),msg_len);
+ in_buffer.remove(0,msg_len);
+ handleMessage ( msg );
+
+ //ulSetError ( UL_DEBUG, "netMessageChannel: %d read", msg_len ) ;
+ n -= msg_len ;
+ }
+ else
+ {
+ //ulSetError ( UL_DEBUG, "netMessageChannel: %d waiting", n ) ;
+ break ;
+ }
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/netMonitor.cpp b/ossimPlanet/src/ossimPlanet/netMonitor.cpp
new file mode 100644
index 0000000..a6761fd
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/netMonitor.cpp
@@ -0,0 +1,180 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netMonitor.cxx 1568 2002-09-02 06:05:49Z sjbaker $
+*/
+
+#include <ossimPlanet/netMonitor.h>
+
+
+class netMonitorChannel : public netChat
+{
+ netMonitorServer* server ;
+ bool authorized ;
+ netBuffer buffer;
+
+ void prompt () ;
+
+ virtual void collectIncomingData (const char* s, int n) ;
+ virtual void foundTerminator (void) ;
+
+public:
+
+ netMonitorChannel ( netMonitorServer* server ) ;
+
+ virtual void handleClose (void)
+ {
+ ulSetError(UL_DEBUG, "%d: Client disconnected.",getHandle());
+ shouldDelete () ;
+ netChat::handleClose () ;
+ server -> active = 0 ;
+ }
+} ;
+
+
+// for now, we ignore any telnet option stuff sent to
+// us, and we process the backspace key ourselves.
+// gee, it would be fun to write a full-blown line-editing
+// environment, etc...
+
+static void clean_line (char* line)
+{
+ char* dst = line ;
+ for ( char* src = line ; *src ; src ++ )
+ {
+ char ch = *src ;
+ if (ch==8 || ch==127)
+ {
+ // backspace
+ if (dst != line)
+ dst -- ;
+ }
+ else if (ch<127)
+ {
+ *dst++ = *src ;
+ }
+ }
+ *dst = 0 ;
+}
+
+
+netMonitorChannel::netMonitorChannel ( netMonitorServer* _server ) : buffer(512)
+{
+ server = _server ;
+ setTerminator("\r\n");
+
+ if ( server -> password && server -> password [0] != 0 )
+ {
+ authorized = false ;
+ push ("Enter password: ") ;
+ }
+ else
+ {
+ authorized = true ;
+ push ( netFormat("Connected to \"%s\"... Welcome!\r\n", server -> name ) ) ;
+ prompt();
+ }
+}
+
+
+void netMonitorChannel::prompt ()
+{
+ push ( server -> prompt ) ;
+}
+
+
+void netMonitorChannel::collectIncomingData (const char* s, int n)
+{
+ if ( !buffer.append(s,n) )
+ {
+ // denial of service.
+ push ("BCNU\r\n");
+ closeWhenDone();
+ }
+}
+
+void netMonitorChannel::foundTerminator (void)
+{
+ char* line = buffer.getData();
+ clean_line ( line ) ;
+
+ if (!authorized)
+ {
+ if (strcmp(line,server -> password) == 0)
+ {
+ authorized = true ;
+ push ( netFormat("Connected to \"%s\"... Welcome!\r\n",server -> name) ) ;
+ prompt () ;
+ }
+ else
+ {
+ close();
+ }
+ }
+ else if (*line == 0)
+ {
+ prompt();
+ }
+ else if (*line == 4 || strcmp(line,"exit") == 0)
+ {
+ push ("BCNU\r\n"); //Be seein' you
+ closeWhenDone();
+ }
+ else
+ {
+ if ( server -> cmdfunc )
+ {
+ server -> cmdfunc ( line ) ;
+ }
+ else
+ {
+ ulSetError(UL_DEBUG,"echo: %s",line);
+
+ push(line);
+ push(getTerminator());
+ }
+
+ prompt();
+ }
+ buffer.remove();
+}
+
+
+void netMonitorServer::handleAccept (void)
+{
+ if ( !active )
+ {
+ netAddress addr ;
+ int s = accept ( &addr ) ;
+
+ ulSetError(UL_DEBUG, "%d: Client %s:%d connected",s,addr.getHost(),addr.getPort());
+
+ active = new netMonitorChannel ( this ) ;
+ active -> setHandle (s);
+ }
+}
+
+
+bool netMonitorServer::push (const char* s)
+{
+ if ( active )
+ return active -> push ( s ) ;
+ return false ;
+}
diff --git a/ossimPlanet/src/ossimPlanet/netSocket.cpp b/ossimPlanet/src/ossimPlanet/netSocket.cpp
new file mode 100644
index 0000000..75a45a9
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/netSocket.cpp
@@ -0,0 +1,503 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: netSocket.cxx 2054 2005-11-16 15:20:57Z bram $
+*/
+
+#include <ossimPlanet/netSocket.h>
+
+#if defined(UL_CYGWIN) || !defined (UL_WIN32)
+
+#if defined(UL_MAC_OSX)
+# include <netinet/in.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>
+#include <sys/time.h> /* Need both for Mandrake 8.0!! */
+#include <unistd.h>
+#include <netdb.h>
+#include <fcntl.h>
+
+#else
+
+#include <winsock.h>
+#include <stdarg.h>
+
+#endif
+
+#if defined(UL_MSVC) && !defined(socklen_t)
+#define socklen_t int
+#endif
+
+/* Paul Wiltsey says we need this for Solaris 2.8 */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned long)-1)
+#endif
+
+netAddress::netAddress ( const char* host, int port )
+{
+ set ( host, port ) ;
+}
+
+
+void netAddress::set ( const char* host, int port )
+{
+ memset(this, 0, sizeof(netAddress));
+
+ sin_family = AF_INET ;
+ sin_port = htons (port);
+
+ /* Convert a string specifying a host name or one of a few symbolic
+ ** names to a numeric IP address. This usually calls gethostbyname()
+ ** to do the work; the names "" and "<broadcast>" are special.
+ */
+
+ if (host[0] == '\0')
+ sin_addr = INADDR_ANY;
+ else
+ if (host[0] == '<' && strcmp(host, "<broadcast>") == 0)
+ sin_addr = INADDR_BROADCAST;
+ else
+ {
+ sin_addr = inet_addr ( host ) ;
+
+ if ( sin_addr == INADDR_NONE )
+ {
+ struct hostent *hp = gethostbyname ( host ) ;
+
+ if ( hp != NULL )
+ memcpy ( (char *) &sin_addr, hp->h_addr, hp->h_length ) ;
+ else
+ {
+ perror ( "netAddress::set" ) ;
+ sin_addr = INADDR_ANY ;
+ }
+ }
+ }
+}
+
+
+/* Create a string object representing an IP address.
+ This is always a string of the form 'dd.dd.dd.dd' (with variable
+ size numbers). */
+
+const char* netAddress::getHost () const
+{
+#if 0
+ const char* buf = inet_ntoa ( sin_addr ) ;
+#else
+ static char buf [32];
+ long x = ntohl(sin_addr);
+ sprintf(buf, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff );
+#endif
+ return buf;
+}
+
+unsigned int netAddress::getIP () const
+{
+ return sin_addr;
+}
+
+unsigned int netAddress::getPort() const
+{
+ return ntohs(sin_port);
+}
+
+unsigned int netAddress::getFamily () const
+{
+ return sin_family;
+}
+
+const char* netAddress::getLocalHost ()
+{
+ //gethostbyname(gethostname())
+
+ char buf[256];
+ memset(buf, 0, sizeof(buf));
+ gethostname(buf, sizeof(buf)-1);
+ const hostent *hp = gethostbyname(buf);
+
+ if (hp && *hp->h_addr_list)
+ {
+ in_addr addr = *((in_addr*)*hp->h_addr_list);
+ const char* host = inet_ntoa(addr);
+
+ if ( host )
+ return host ;
+ }
+
+ return "127.0.0.1" ;
+}
+
+
+bool netAddress::getBroadcast () const
+{
+ return sin_addr == INADDR_BROADCAST;
+}
+
+
+netSocket::netSocket ()
+{
+ handle = -1 ;
+}
+
+
+netSocket::~netSocket ()
+{
+ close () ;
+}
+
+
+void netSocket::setHandle (int _handle)
+{
+ close () ;
+ handle = _handle ;
+}
+
+
+bool netSocket::open ( bool stream )
+{
+ close () ;
+ handle = ::socket ( AF_INET, (stream? SOCK_STREAM: SOCK_DGRAM), 0 ) ;
+ return (handle != -1);
+}
+
+
+void netSocket::setBlocking ( bool blocking )
+{
+ assert ( handle != -1 ) ;
+
+#if defined(UL_CYGWIN) || !defined (UL_WIN32)
+
+ int delay_flag = ::fcntl (handle, F_GETFL, 0);
+
+ if (blocking)
+ delay_flag &= (~O_NDELAY);
+ else
+ delay_flag |= O_NDELAY;
+
+ ::fcntl (handle, F_SETFL, delay_flag);
+
+#else
+
+ u_long nblocking = blocking? 0: 1;
+ ::ioctlsocket(handle, FIONBIO, &nblocking);
+
+#endif
+}
+
+
+void netSocket::setBroadcast ( bool broadcast )
+{
+ assert ( handle != -1 ) ;
+ int result;
+ if ( broadcast ) {
+ int one = 1;
+#ifdef UL_WIN32
+ result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one) );
+#else
+ result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one) );
+#endif
+ } else {
+ result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, NULL, 0 );
+ }
+ if ( result < 0 ) {
+ perror("set broadcast:");
+ }
+ assert ( result != -1 );
+}
+
+
+int netSocket::bind ( const char* host, int port )
+{
+ assert ( handle != -1 ) ;
+ netAddress addr ( host, port ) ;
+ return ::bind(handle,(const sockaddr*)&addr,sizeof(netAddress));
+}
+
+
+int netSocket::listen ( int backlog )
+{
+ assert ( handle != -1 ) ;
+ return ::listen(handle,backlog);
+}
+
+
+int netSocket::accept ( netAddress* addr )
+{
+ assert ( handle != -1 ) ;
+
+ if ( addr == NULL )
+ {
+ return ::accept(handle,NULL,NULL);
+ }
+ else
+ {
+ socklen_t addr_len = (socklen_t) sizeof(netAddress) ;
+ return ::accept(handle,(sockaddr*)addr,&addr_len);
+ }
+}
+
+
+int netSocket::connect ( const char* host, int port )
+{
+ assert ( handle != -1 ) ;
+ netAddress addr ( host, port ) ;
+ if ( addr.getBroadcast() ) {
+ setBroadcast( true );
+ }
+ return ::connect(handle,(const sockaddr*)&addr,sizeof(netAddress));
+}
+
+
+int netSocket::send (const void * buffer, int size, int flags)
+{
+ assert ( handle != -1 ) ;
+ return ::send (handle, (const char*)buffer, size, flags);
+}
+
+
+int netSocket::sendto ( const void * buffer, int size,
+ int flags, const netAddress* to )
+{
+ assert ( handle != -1 ) ;
+ return ::sendto(handle,(const char*)buffer,size,flags,
+ (const sockaddr*)to,sizeof(netAddress));
+}
+
+
+int netSocket::recv (void * buffer, int size, int flags)
+{
+ assert ( handle != -1 ) ;
+ return ::recv (handle, (char*)buffer, size, flags);
+}
+
+
+int netSocket::recvfrom ( void * buffer, int size,
+ int flags, netAddress* from )
+{
+ assert ( handle != -1 ) ;
+ socklen_t fromlen = (socklen_t) sizeof(netAddress) ;
+ return ::recvfrom(handle,(char*)buffer,size,flags,(sockaddr*)from,&fromlen);
+}
+
+
+void netSocket::close (void)
+{
+ if ( handle != -1 )
+ {
+#if defined(UL_CYGWIN) || !defined (UL_WIN32)
+ ::close( handle );
+#else
+ ::closesocket( handle );
+#endif
+ handle = -1 ;
+ }
+}
+
+
+bool netSocket::isNonBlockingError ()
+{
+#if defined(UL_CYGWIN) || !defined (UL_WIN32)
+ switch (errno) {
+ case EWOULDBLOCK: // always == NET_EAGAIN?
+ case EALREADY:
+ case EINPROGRESS:
+ return true;
+ }
+ return false;
+#else
+ int wsa_errno = WSAGetLastError();
+ if ( wsa_errno != 0 )
+ {
+ WSASetLastError(0);
+ ulSetError(UL_WARNING,"WSAGetLastError() => %d",wsa_errno);
+ switch (wsa_errno) {
+ case WSAEWOULDBLOCK: // always == NET_EAGAIN?
+ case WSAEALREADY:
+ case WSAEINPROGRESS:
+ return true;
+ }
+ }
+ return false;
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// modified version by os
+//
+//////////////////////////////////////////////////////////////////////
+int netSocket::select ( netSocket** reads, netSocket** writes, int timeout )
+{
+ fd_set r,w;
+ int retval;
+
+ FD_ZERO (&r);
+ FD_ZERO (&w);
+
+ int i, k ;
+ int num = 0 ;
+
+ if ( reads )
+ {
+ for ( i=0; reads[i]; i++ )
+ {
+ int fd = reads[i]->getHandle();
+ FD_SET (fd, &r);
+ num++;
+ }
+ }
+
+ if ( writes )
+ {
+ for ( i=0; writes[i]; i++ )
+ {
+ int fd = writes[i]->getHandle();
+ FD_SET (fd, &w);
+ num++;
+ }
+ }
+
+ if (!num)
+ return num ;
+
+ /* Set up the timeout */
+ struct timeval tv ;
+ tv.tv_sec = timeout/1000;
+ tv.tv_usec = (timeout%1000)*1000;
+
+ // It bothers me that select()'s first argument does not appear to
+ // work as advertised... [it hangs like this if called with
+ // anything less than FD_SETSIZE, which seems wasteful?]
+
+ // Note: we ignore the 'exception' fd_set - I have never had a
+ // need to use it. The name is somewhat misleading - the only
+ // thing I have ever seen it used for is to detect urgent data -
+ // which is an unportable feature anyway.
+
+ retval = ::select (FD_SETSIZE, &r, &w, 0, &tv);
+
+ //remove sockets that had no activity
+
+ num = 0 ;
+
+ if ( reads )
+ {
+ for ( k=i=0; reads[i]; i++ )
+ {
+ int fd = reads[i]->getHandle();
+ if ( FD_ISSET (fd, &r) )
+ {
+ reads[k++] = reads[i];
+ num++;
+ }
+ }
+ reads[k] = NULL ;
+ }
+
+ if ( writes )
+ {
+ for ( k=i=0; writes[i]; i++ )
+ {
+ int fd = writes[i]->getHandle();
+ if ( FD_ISSET (fd, &w) )
+ {
+ writes[k++] = writes[i];
+ num++;
+ }
+ }
+ writes[k] = NULL ;
+ }
+
+ if (retval == 0) // timeout
+ return (-2);
+ if (retval == -1)// error
+ return (-1);
+
+ return num ;
+}
+
+
+/* Init/Exit functions */
+
+static void netExit ( void )
+{
+#if defined(UL_CYGWIN) || !defined (UL_WIN32)
+#else
+ /* Clean up windows networking */
+ if ( WSACleanup() == SOCKET_ERROR ) {
+ if ( WSAGetLastError() == WSAEINPROGRESS ) {
+ WSACancelBlockingCall();
+ WSACleanup();
+ }
+ }
+#endif
+}
+
+
+int netInit ( int* argc, char** argv )
+{
+ /* Legacy */
+
+ return netInit () ;
+}
+
+
+int netInit ()
+{
+ assert ( sizeof(sockaddr_in) == sizeof(netAddress) ) ;
+
+#if defined(UL_CYGWIN) || !defined (UL_WIN32)
+#else
+ /* Start up the windows networking */
+ WORD version_wanted = MAKEWORD(1,1);
+ WSADATA wsaData;
+
+ if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
+ ulSetError(UL_WARNING,"Couldn't initialize Winsock 1.1");
+ return(-1);
+ }
+#endif
+
+ atexit( netExit ) ;
+ return(0);
+}
+
+
+const char* netFormat ( const char* format, ... )
+{
+ static char buffer[ 256 ];
+ va_list argptr;
+ va_start(argptr, format);
+ vsprintf( buffer, format, argptr );
+ va_end(argptr);
+ return( buffer );
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanet.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanet.cpp
new file mode 100644
index 0000000..15b5a05
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanet.cpp
@@ -0,0 +1,507 @@
+#include <osg/Timer>
+#include <osg/BoundingSphere>
+#include <osg/CoordinateSystemNode>
+#include <osgDB/DatabasePager>
+#include <osgDB/Registry>
+#include <osgUtil/IntersectVisitor>
+#include <iostream>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossimPlanet/ossimPlanetLayerRegistry.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <iostream>
+// #include <ossimPlanet/ossimPlanetUtility.h>
+
+// #include <ossimPlanet/ossimPlanetLatLonHud.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+
+#include <OpenThreads/ScopedLock>
+ossimPlanet::LayerListener::LayerListener(ossimPlanet* planet)
+:thePlanet(planet)
+{
+}
+void ossimPlanet::LayerListener::needsRedraw(ossimPlanetNode* node)
+{
+ if(thePlanet)
+ {
+ thePlanet->setRedrawFlag(true);
+ thePlanet->notifyNeedsRedraw(node);
+ }
+}
+void ossimPlanet::LayerListener::setPlanet(ossimPlanet* planet)
+{
+ thePlanet = planet;
+}
+
+class ossimPlanetFinder : public osg::NodeVisitor
+{
+public:
+ ossimPlanetFinder()
+ :osg::NodeVisitor(NODE_VISITOR,
+ TRAVERSE_ALL_CHILDREN)
+ {
+ thePlanet = 0;
+ }
+
+ virtual void apply(osg::Node& node)
+ {
+ if(!thePlanet)
+ {
+ thePlanet = dynamic_cast<ossimPlanet*>(&node);
+ }
+ else
+ {
+ return;
+ }
+ osg::NodeVisitor::apply(node);
+ }
+
+ ossimPlanet* thePlanet;
+};
+
+class ossimPlanetResetRedrawFlag : public osg::NodeVisitor
+{
+public:
+ ossimPlanetResetRedrawFlag()
+ :osg::NodeVisitor(NODE_VISITOR,
+ TRAVERSE_ALL_CHILDREN)
+ {
+
+ }
+ virtual void apply(osg::Node& node)
+ {
+ ossimPlanetLayer* layer = dynamic_cast<ossimPlanetLayer*>(&node);
+ if(layer)
+ {
+ layer->setRedrawFlag(false);
+ }
+
+ osg::NodeVisitor::apply(node);
+ }
+
+};
+
+osg::BoundingSphere ossimPlanet::computeBound() const
+{
+ if(getNumChildren() == 0)
+ {
+ return osg::BoundingSphere(osg::Vec3(0.0,0.0,0.0),
+ 1.0);
+ }
+ return osg::MatrixTransform::computeBound();
+
+}
+
+//bool ossimPlanet::computeBound() const
+//{
+// if(getNumChildren() == 0)
+// {
+// _bsphere = osg::BoundingSphere(osg::Vec3(0.0,0.0,0.0),
+// 1.0);
+// }
+// else
+// {
+// return osg::MatrixTransform::computeBound();
+// }
+// return true;
+// }
+
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static ossim_uint32 allocated = 0;
+#endif
+ossimPlanet::ossimPlanet()
+ :osg::MatrixTransform()
+{
+ theNadirPoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theLineOfSitePoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theNadirLatLonHeightPoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theLineOfSiteLatLonHeightPoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theLayerListener = new ossimPlanet::LayerListener(this);
+ theRedrawFlag = false;
+ theComputeIntersectionFlag = true;
+ setUpdateCallback(new ossimPlanetTraverseCallback);
+ setEventCallback(new ossimPlanetTraverseCallback);
+ setCullCallback(new ossimPlanetTraverseCallback);
+
+ theModel = new ossimPlanetNormalizedEllipsoidModel;
+
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++allocated;
+ std::cout << "ossimPlanet count: " << allocated << std::endl;
+#endif
+}
+
+ossimPlanet::~ossimPlanet()
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ --allocated;
+ std::cout << "ossimPlanet count: " << allocated << std::endl;
+#endif
+
+}
+void ossimPlanet::setupDefaults()
+{
+}
+
+
+void ossimPlanet::traverse(osg::NodeVisitor& nv)
+{
+// osg::Timer_t tick = osg::Timer::instance()->tick();
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osg::MatrixTransform::traverse(nv);
+ return;
+ }
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ // we are starting a redraw for the update,cull,draw sequence so reset the redraw flag for next frame
+ theLayersToAddListMutex.lock();
+ if(theLayersToAddList.size())
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theLayersToAddList.size();++idx)
+ {
+ addChild(theLayersToAddList[idx].get());
+ }
+ theLayersToAddList.clear();
+ }
+ theLayersToAddListMutex.unlock();
+
+ break;
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ osg::MatrixTransform::traverse(nv);
+#if 0
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ std::cout << "event TIME == "
+ << osg::Timer::instance()->delta_m(tick, osg::Timer::instance()->tick()) << std::endl;
+ break;
+ }
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ std::cout << "update TIME == "
+ << osg::Timer::instance()->delta_m(tick, osg::Timer::instance()->tick()) << std::endl;
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ std::cout << "CULLING TIME == "
+ << osg::Timer::instance()->delta_m(tick, osg::Timer::instance()->tick()) << std::endl;
+ break;
+ }
+ }
+#endif
+}
+
+const osg::Vec3d& ossimPlanet::getEyePositionLatLonHeight()const
+{
+ return theEyePositionLatLonHeight;
+}
+
+osg::Vec3d ossimPlanet::getNadirPoint()const
+{
+ return theNadirPoint;
+}
+
+osg::Vec3d ossimPlanet::getLineOfSitePoint()const
+{
+ return theLineOfSitePoint;
+}
+
+
+osg::Vec3d ossimPlanet::getNadirLatLonHeightPoint()const
+{
+ return theNadirLatLonHeightPoint;
+}
+
+osg::Vec3d ossimPlanet::getLineOfSiteLatLonHeightPoint()const
+{
+ return theLineOfSiteLatLonHeightPoint;
+}
+
+const osg::Vec3d& ossimPlanet::hpr()const
+{
+ return theLsrHeadingPitchRoll;
+}
+
+void ossimPlanet::setComputeIntersectionFlag(bool flag)
+{
+ theComputeIntersectionFlag = flag;
+}
+
+bool ossimPlanet::getComputeIntersectionFlag()const
+{
+ return theComputeIntersectionFlag;
+}
+
+void ossimPlanet::computeIntersection(osgUtil::CullVisitor* nv)
+{
+ theNadirPoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theLineOfSitePoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theNadirLatLonHeightPoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ theLineOfSiteLatLonHeightPoint = osg::Vec3d(0.0,0.0,ossim::nan());
+ if(!nv)
+ {
+ return;
+ }
+ osg::Node* node = 0;
+ if(getNumChildren() > 0)
+ {
+ node = getChild(0);
+ }
+ if(node)
+ {
+ if(theModel.valid())
+ {
+ osgUtil::IntersectVisitor iv;
+ osg::Vec3d eyeDirection = nv->getLookVectorLocal();
+ osg::Vec3d eye = nv->getEyePoint();
+ osg::Vec3d normal;
+ osg::Vec3d eyeLlh;
+ theModel->inverse(eye,
+ eyeLlh);
+ theModel->normal(eyeLlh,
+ normal);
+ normal.normalize();
+ osg::Vec3d endPt1 = getBound().center();
+ osg::Vec3d endPt2 = eye + eyeDirection*(1/FLT_EPSILON);
+ osg::Vec3d startPt3 = eye + normal*(1/FLT_EPSILON);
+ osg::ref_ptr<osg::LineSegment> nadirLookVector = new osg::LineSegment(startPt3, endPt1);
+ osg::ref_ptr<osg::LineSegment> lineOfSiteLookVector = new osg::LineSegment(eye, endPt2);
+ iv.addLineSegment(nadirLookVector.get());
+ iv.addLineSegment(lineOfSiteLookVector.get());
+ node->accept(iv);
+// this->accept(iv);
+ if(iv.hits())
+ {
+// osg::Vec3d eyeLocal = nv->getEyeLocal();
+
+// theNadirPoint = eyeLocal;
+// land()->model()->inverse(theNadirPoint,
+// theNadirLatLonHeightPoint);
+
+ osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(lineOfSiteLookVector.get());
+ if (!hitList.empty())
+ {
+ theLineOfSitePoint = hitList.front().getWorldIntersectPoint();
+ theModel->inverse(theLineOfSitePoint,
+ theLineOfSiteLatLonHeightPoint);
+ }
+ osgUtil::IntersectVisitor::HitList& hitListNadir = iv.getHitList(nadirLookVector.get());
+ if (!hitListNadir.empty())
+ {
+ theNadirPoint = hitListNadir.front().getWorldIntersectPoint();
+ theModel->inverse(theNadirPoint,
+ theNadirLatLonHeightPoint);
+ }
+ }
+ }
+ }
+}
+
+ossimPlanet* ossimPlanet::findPlanet(osg::Node* startNode)
+{
+ osg::Node* rootNode = startNode;
+ osg::Node* rootNonNullNode = startNode;
+
+ while(rootNode)
+ {
+ rootNonNullNode = rootNode;
+ if(dynamic_cast<ossimPlanet*>(rootNode))
+ {
+ return (ossimPlanet*)rootNode;
+ }
+ if(rootNode->getNumParents() > 0)
+ {
+ rootNode = rootNode->getParent(0);
+ }
+ else
+ {
+ rootNode = 0;
+ }
+ }
+ if(rootNonNullNode)
+ {
+ ossimPlanetFinder finder;
+ rootNonNullNode->accept(finder);
+ if(finder.thePlanet)
+ {
+ return finder.thePlanet;
+ }
+ }
+
+ return 0;
+}
+
+ossimPlanet* ossimPlanet::findPlanet(osg::NodePath& currentNodePath)
+{
+ if(currentNodePath.empty())
+ {
+ return 0;
+ }
+ for(osg::NodePath::reverse_iterator itr = currentNodePath.rbegin();
+ itr != currentNodePath.rend();
+ ++itr)
+ {
+ ossimPlanet* node = dynamic_cast<ossimPlanet*>(*itr);
+ if (node)
+ {
+ return node;
+ }
+ }
+
+ return 0;
+}
+
+void ossimPlanet::resetAllRedrawFlags()
+{
+ ossimPlanetResetRedrawFlag resetRedraw;
+ setRedrawFlag(false);
+ accept(resetRedraw);
+}
+
+
+void ossimPlanet::execute(const ossimPlanetAction& action)
+{
+ const ossimPlanetXmlAction* xmlAction = action.toXmlAction();
+
+ if(xmlAction)
+ {
+ xmlExecute(*xmlAction);
+ if(action.command() == "Add")
+ {
+
+ }
+ }
+}
+
+void ossimPlanet::xmlExecute(const ossimPlanetXmlAction& action)
+{
+ if(action.command() == "Add")
+ {
+ }
+}
+
+bool ossimPlanet::removeChildren(unsigned int pos,unsigned int numChildrenToRemove)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag)
+ {
+ return osg::MatrixTransform::removeChildren(pos, numChildrenToRemove);
+ }
+ }
+
+ if (pos<_children.size() && numChildrenToRemove>0)
+ {
+ unsigned int endOfRemoveRange = pos+numChildrenToRemove;
+ if (endOfRemoveRange>_children.size())
+ {
+ endOfRemoveRange=_children.size();
+ }
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < endOfRemoveRange;++idx)
+ {
+ ossimPlanetLayer* layer = dynamic_cast<ossimPlanetLayer*>(_children[idx].get());
+ if(layer)
+ {
+ notifyLayerRemoved(layer);
+ }
+ }
+ return osg::MatrixTransform::removeChildren(pos, numChildrenToRemove);
+ }
+ else return false;
+}
+
+void ossimPlanet::childInserted(unsigned int pos)
+{
+ ossimPlanetLayer* n = dynamic_cast<ossimPlanetLayer*>(getChild(pos));
+// if(!theLand.valid())
+// {
+// ossimPlanetLand* land = dynamic_cast<ossimPlanetLand*>(n);
+// if(land)
+// {
+// theLand = land;
+// theModel = theLand->model();
+// }
+// }
+ {
+ if(theBlockCallbacksFlag) return;
+ }
+ if(n)
+ {
+ n->setPlanet(this);
+ n->setModel(model().get());
+ setRedrawFlag(true);
+ n->addCallback(theLayerListener.get());
+ notifyLayerAdded(n);
+ }
+}
+
+void ossimPlanet::childRemoved(unsigned int /*pos*/, unsigned int /*numChildrenToRemove*/)
+{
+ setRedrawFlag(true);
+}
+
+void ossimPlanet::notifyLayerAdded(ossimPlanetLayer* layer)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->nodeAdded(layer);
+ }
+ }
+}
+
+void ossimPlanet::notifyLayerRemoved(ossimPlanetLayer* layer)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->nodeRemoved(layer);
+ }
+ }
+
+}
+
+void ossimPlanet::notifyNeedsRedraw(ossimPlanetNode* node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->needsRedraw(node);
+ }
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetAction.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetAction.cpp
new file mode 100644
index 0000000..466559e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetAction.cpp
@@ -0,0 +1,55 @@
+#include <iostream>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimCommon.h>
+
+ossimPlanetAction::ossimPlanetAction(const ossimString& originatingFederate) :
+ theOrigin(originatingFederate)
+{
+}
+
+
+
+void ossimPlanetAction::printError(const char* message) const
+{
+ ossimString code;
+ sourceCode(code);
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetAction Error (" << message << ") \"" << code << '"' << std::endl;
+}
+
+void ossimPlanetAction::printError(const ossimString& message) const
+{
+ printError(message.c_str());
+}
+
+void ossimPlanetAction::execute() const
+{
+ ossimPlanetActionRouter::instance()->route(*this);
+}
+
+void ossimPlanetAction::post()const
+{
+ ossimPlanetActionRouter::instance()->post(*this);
+}
+
+void ossimPlanetAction::allExecute() const
+{
+ ossimPlanetActionRouter::instance()->allRoute(*this);
+}
+
+void ossimPlanetAction::tellExecute(const ossimString& destination) const
+{
+ ossimPlanetActionRouter::instance()->tellRoute(*this, destination);
+}
+
+
+// protected
+
+
+const ossimString& ossimPlanetAction::defaultOrigin()
+{
+ return ossimPlanetActionRouter::instance()->federateName();
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetActionReceiver.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetActionReceiver.cpp
new file mode 100644
index 0000000..d6ac321
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetActionReceiver.cpp
@@ -0,0 +1,31 @@
+#include <ossimPlanet/ossimPlanetActionReceiver.h>
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+
+ossimPlanetActionReceiver::~ossimPlanetActionReceiver()
+{
+ if (pathname_ != ":")
+ ossimPlanetActionRouter::instance()->unregisterReceiver(this);
+}
+
+std::string ossimPlanetActionReceiver::name() const
+{
+ return pathname_.substr(pathname_.rfind(':')+1, pathname_.length());
+}
+
+void ossimPlanetActionReceiver::setPathname(const std::string& newPath)
+{
+ pathname_ = newPath;
+}
+
+void ossimPlanetActionReceiver::setPathnameAndRegister(const std::string& newPath)
+{
+ // we will unregister if already registered
+ //
+ ossimPlanetActionReceiver* r = ossimPlanetActionRouter::instance()->receiver(pathname());
+ if(r==this) // if we are ourselves then we can change our pathname
+ {
+ ossimPlanetActionRouter::instance()->unregisterReceiver(this);
+ }
+ setPathname(newPath);
+ ossimPlanetActionRouter::instance()->registerReceiver(this);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetActionRouter.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetActionRouter.cpp
new file mode 100644
index 0000000..e78690f
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetActionRouter.cpp
@@ -0,0 +1,374 @@
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <limits.h>
+#ifndef WIN32
+#include <sys/param.h>
+#else
+#include <winsock.h>
+#endif
+
+#include <osgDB/FileUtils>
+
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+#include <ossimPlanet/ossimPlanetSocketNetworkConnection.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+
+using namespace mkUtils;
+
+
+// network
+
+void ossimPlanetActionRouter::addNetworkConnection(ossimPlanetNetworkConnection* commLink)
+{
+ if(commLink&&commLink->error().empty())
+ {
+// assert(commLink != NULL && commLink->error().empty());
+
+ std::vector<ossimPlanetNetworkConnection*>::iterator i = find_if(network_.begin(), network_.end(), NCEqualPred(commLink->name()));
+ if (i == network_.end())
+ network_.push_back(commLink);
+ else
+ std::cerr << "ossimPlanetActionRouter::addNetworkConnection() already has a ossimPlanetNetworkConnection named " << commLink->name() << std::endl;
+ }
+}
+
+void ossimPlanetActionRouter::removeNetworkConnection(const ossimString& name)
+{
+ std::vector<ossimPlanetNetworkConnection*>::iterator i = find_if(network_.begin(), network_.end(), NCEqualPred(name));
+ if (i != network_.end())
+ network_.erase(i);
+}
+
+ossimPlanetNetworkConnection* ossimPlanetActionRouter::networkConnection(const ossimString& name) const
+{
+ std::vector<ossimPlanetNetworkConnection*>::const_iterator i = find_if(network_.begin(), network_.end(), NCEqualPred(name));
+ return i == network_.end() ? NULL : *i;
+}
+
+// federate name
+
+void ossimPlanetActionRouter::setFederateName(const ossimString& newName)
+{
+
+ if(ossimString(newName).trim().empty()) return;
+
+// assert(!newName.empty());
+// assert(newName.find(" ", 0) == -1);
+
+ federateName_ = newName;
+
+// assert(newName == federateName());
+}
+
+void ossimPlanetActionRouter::post(const ossimPlanetAction& a)
+{
+ if(theThreadQueue.valid())
+ {
+ theThreadQueue->addAction(a);
+ }
+}
+
+// route Actions
+
+void ossimPlanetActionRouter::route(const ossimPlanetAction& a)
+{
+ ossimPlanetActionReceiver * receiver = 0;
+ ossimString target(a.target());
+
+ // start critical section
+ theReceiverMutex.lock();
+
+ MapType::iterator targetObj = receivers_.find(target);
+ if (targetObj != receivers_.end())
+ {
+ receiver = targetObj->second;
+ }
+ theReceiverMutex.unlock();
+ // end critical section
+
+ if (receiver)
+ {
+ // found a receiver so exectute the action
+ receiver->execute(a);
+ }
+ else
+ {
+ a.printError("bad target for action");
+ }
+}
+
+void ossimPlanetActionRouter::allRoute(const ossimPlanetAction& a)
+{
+ static const ossimString emptyString; // static since don't ctor/dtor empty string every time
+ remoteRouteImplementation(a, emptyString);
+}
+
+void ossimPlanetActionRouter::tellRoute(const ossimPlanetAction& a, const ossimString& destination)
+{
+ if(destination.empty()) return;
+
+// assert(!destination.empty());
+ remoteRouteImplementation(a, destination);
+}
+
+void ossimPlanetActionRouter::executeFile(const ossimString& filename, const ossimString& origin)
+{
+#if 0 // XXX crash in osgDB::findFileInPath(), so junk the search path until we figure this out
+ ossimString searchResult = osgDB::findFileInPath(filename, osgDB::getDataFilePathList());
+ std::ifstream fin(searchResult.empty() ? filename.c_str() : searchResult.c_str());
+#else
+ std::ifstream fin(filename.c_str());
+#endif
+
+ if (!fin)
+ ossimNotify(ossimNotifyLevel_WARN) << "cannot open file " << filename << " for execution in ossimPlanetActionRouter::executeFile()" << std::endl;
+ else
+ {
+ ossimPlanetDestinationCommandAction x("", origin);
+ for (fin >> x; fin; fin >> x)
+ {
+ route(x);
+ x.setSourceCode("");
+ }
+ ossimString code;
+ x.sourceCode(code);
+ if(fin.eof()&&!code.empty())
+ {
+ route(x);
+ }
+ }
+}
+
+void ossimPlanetActionRouter::executeNetworkActions()
+{
+ for (int i = 0; i < (int)network_.size(); i++)
+ network_[i]->receive();
+}
+
+// ossimPlanetActionReceiver management
+
+void ossimPlanetActionRouter::registerReceiver(ossimPlanetActionReceiver* r)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReceiverMutex);
+ if(!r) return;
+// assert(r != NULL);
+
+ // If a receiver with this name was already registered,
+ // tell us before we replace it with r.
+ MapType::iterator i = receivers_.find(r->pathname());
+ if (i != receivers_.end())
+ std::cerr << "\aWarning in ossimPlanetActionRouter::registerReceiver: ossimPlanetActionReceiver " << i->second << " with pathname " << r->pathname() << " already registered, replacing with ossimPlanetActionReceiver " << r << std::endl;
+
+ receivers_[r->pathname()] = r;
+
+// assert(receiver(r->pathname()) == r);
+}
+
+void ossimPlanetActionRouter::unregisterReceiver(ossimPlanetActionReceiver* r)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReceiverMutex);
+ if(!r) return;
+// assert(r != NULL);
+
+ MapType::iterator i = receivers_.find(r->pathname());
+ if(i!=receivers_.end())
+ {
+ if (i->second == r)
+ {
+ // r is registered under r->pathname().
+ // this is the normal case.
+ receivers_.erase(i);
+
+ }
+ else if (i->second == NULL)
+ {
+ // r not registered under r->pathname(), unknown yet if r is registered
+ // under a different name. if so, find it and remove it.
+ for (i = receivers_.begin(); i != receivers_.end() && i->second != r; i++)
+ ;
+ if (i != receivers_.end())
+ {
+ receivers_.erase(i);
+ }
+ }
+ else
+ {
+ // some other receiver is registered under r->pathname().
+ // the Reaper'd case. maybe other cases? noop is the correct response.
+ }
+ }
+ else
+ {
+ for (i = receivers_.begin(); i != receivers_.end() && i->second != r; i++)
+ ;
+ if (i != receivers_.end())
+ {
+ receivers_.erase(i);
+ }
+ }
+// assert(receiver(r->pathname()) != r);
+}
+
+ossimPlanetActionReceiver* ossimPlanetActionRouter::receiver(const ossimString& receiverPathname) const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReceiverMutex);
+ ossimPlanetActionReceiver* result = NULL;
+ MapType::const_iterator r = receivers_.find(receiverPathname);
+
+ if (r != receivers_.end())
+ result = r->second;
+
+// assert(result == NULL || result->pathname() == receiverPathname);
+
+ return result;
+}
+
+void ossimPlanetActionRouter::printReceivers()
+{
+ int i = 0;
+ MapType::iterator r;
+
+ for (r = receivers_.begin(); r != receivers_.end(); r++)
+ std::cout << i++ << " = " << r->first << std::endl;
+}
+
+// ossimPlanetActionReceiver features
+
+void ossimPlanetActionRouter::execute(const ossimPlanetAction& action)
+{
+ const ossimPlanetDestinationCommandAction* a = action.toDestinationCommandAction();
+ // for now only support :destination command <args> style actions;
+ if(!a) return;
+
+ ossimString command;
+ a->command(command);
+ if (command == "#") {
+ // this action is a comment, so do nothing
+
+ } else if (command == "#syntaxerror") {
+ a->printError("illegal Action syntax");
+
+ } else if (command == "echo") {
+ std::cout << a->argListSource() << std::endl;
+
+ } else if (command == "execfiles") {
+ for (unsigned int i = 1; i <= a->argCount(); i++)
+ executeFile(a->arg(i));
+
+ } else if (command == "execactions") {
+ ossimPlanetDestinationCommandAction x;
+ for (unsigned int i = 1; i <= a->argCount(); i++) {
+ x.setSourceCode(a->arg(i));
+ route(x);
+ }
+
+ } else if (command == "shell") {
+ system(a->argListSource().c_str());
+
+ }
+ else if (command == "manualaction")
+ {
+ std::cout << "Enter action\n> " << std::flush;
+ ossimPlanetDestinationCommandAction x;
+ std::cin >> x;
+ route(x);
+
+ } else if (command == "printreceivers") {
+ printReceivers();
+
+ } else if (command == "setfederatename") {
+ if (a->argCount() == 1)
+ setFederateName(a->arg(1));
+ else
+ a->printError("bad argument count");
+
+ }
+ else if (command == "opensocket")
+ {
+ if ((a->argCount() == 2 && isInt(a->arg(2))) || (a->argCount() == 3 && isInt(a->arg(2)) && isInt(a->arg(3)))) {
+ char delimiter = a->argCount() == 2 ? '\n' : static_cast<char>(asInt(a->arg(3)));
+ ossimPlanetSocketNetworkConnection* s = new ossimPlanetSocketNetworkConnection(a->arg(1), asInt(a->arg(2)), delimiter);
+ if (!s->error().empty()) {
+ a->printError("SocketNetworkConnection had this error: " + s->error());
+ delete s;
+ } else
+ addNetworkConnection(s);
+ } else
+ a->printError("bad argument count or type, needs one string (host) and one int (port) and optionally one string ('nul' or 'newline')");
+
+ }
+ else if (command == "closesocket")
+ {
+ if (a->argCount() == 2 && isInt(a->arg(2)))
+ {
+ ossimString name = a->arg(1) + ":" + a->arg(2);
+ ossimPlanetSocketNetworkConnection* s = dynamic_cast<ossimPlanetSocketNetworkConnection*>(networkConnection(name));
+ if (s == NULL)
+ a->printError("could not find a SocketNetworkConnection named: " + name);
+ else
+ removeNetworkConnection(s->name());
+ delete s;
+ }
+ else
+ a->printError("bad argument count or type, needs one string (host) and one int (port)");
+
+ }
+ else
+ {
+ a->printError("ActionRouter action not understood");
+ }
+}
+
+// protected
+
+
+ossimPlanetActionRouter* ossimPlanetActionRouter::instance_ = 0;
+
+ossimPlanetActionRouter::ossimPlanetActionRouter() :
+ federateName_("DefaultFederateName-")
+{
+ // NB: can't use setPathnameAndRegister here, it will trigger infinite
+ // recursive calls to this ctor since instance_ is still NULL right now.
+ setPathname(":");
+ registerReceiver(this);
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+ // Build a default process name that includes hostname and pid.
+ char buffer[MAXHOSTNAMELEN];
+ buffer[0] = '\0';
+ gethostname(buffer, MAXHOSTNAMELEN);
+ federateName_.append(buffer);
+ federateName_.append("-");
+#ifdef WIN32
+ federateName_.append(asString(GetCurrentProcessId()));
+#else
+ federateName_.append(asString(getpid()));
+#endif
+}
+
+ossimPlanetActionRouter::~ossimPlanetActionRouter()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReceiverMutex);
+ receivers_.clear();
+ if(theThreadQueue.valid())
+ {
+ theThreadQueue->cancel();
+ }
+ for (int i = 0; i < (int)network_.size(); i++)
+ delete network_[i];
+}
+
+void ossimPlanetActionRouter::remoteRouteImplementation(const ossimPlanetAction& a, const ossimString& destination)
+{
+ if (destination != federateName_)
+ for (int i = 0; i < (int)network_.size(); i++)
+ network_[i]->send(a, destination);
+
+ if (destination.empty() || destination == federateName_)
+ route(a);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetAnimatedPointModel.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetAnimatedPointModel.cpp
new file mode 100644
index 0000000..535b82c
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetAnimatedPointModel.cpp
@@ -0,0 +1,307 @@
+#include <ossimPlanet/ossimPlanetAnimatedPointModel.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+
+ossimPlanetAnimatedPointModel::ossimPlanetAnimatedPointModel()
+:theShowPathFlag(true),
+theShowModelFlag(true),
+theAnimationPathColor(1.0,0.0,0.0,.5),
+theAnimationPathLineThickness(2.0)
+{
+ setCullingActive(false);
+ thePathMatrixTransform = new osg::MatrixTransform();
+ thePathColor = new osg::Vec4Array();
+ thePathVertices = new osg::Vec3Array();
+ thePathGeode = new osg::Geode();
+ thePathGeometry = new osg::Geometry();
+ theLineWidth = new osg::LineWidth(theAnimationPathLineThickness);
+ thePathColor->push_back(theAnimationPathColor);
+ // add the points geometry to the geode.
+ thePathGeode->addDrawable(thePathGeometry.get());
+ thePathMatrixTransform->addChild(thePathGeode.get());
+
+ theAnimationPathCallback = new ossimPlanetAnimatedPointModel::PathCallback();
+}
+
+ossimPlanetAnimatedPointModel::~ossimPlanetAnimatedPointModel()
+{
+ if(thePointModel.valid())
+ {
+ thePointModel->setUpdateCallback(0);
+ }
+ if(theAnimationPathCallback.valid())
+ {
+ theAnimationPathCallback->setAnimationPath(0);
+ }
+}
+
+void ossimPlanetAnimatedPointModel::execute(const ossimPlanetAction& action)
+{
+ ossimPlanetAnnotationLayerNode::execute(action);
+}
+
+void ossimPlanetAnimatedPointModel::setAnimationPath(ossimPlanetAnimationPath* path)
+{
+ setDirtyBit((DirtyBit)(COLOR_DIRTY|COORDINATE_DIRTY)); // this will dirty everything so all is regenerated
+ theAnimationPath = path;
+
+ theAnimationPathCallback->setAnimationPath(theAnimationPath.get());
+}
+
+void ossimPlanetAnimatedPointModel::setAnimationPathColor(const osg::Vec4f& value)
+{
+ setDirtyBit(COLOR_DIRTY); // this will rest color and thickness for the path
+ theAnimationPathColor = value;
+}
+
+void ossimPlanetAnimatedPointModel::setAnimationPathLineThickness(ossim_float32 value)
+{
+ setDirtyBit(COLOR_DIRTY); // let's just reset color and thickness always
+ theAnimationPathLineThickness = value;
+}
+
+void ossimPlanetAnimatedPointModel::setShowPathFlag(bool flag)
+{
+ theShowPathFlag = flag;
+}
+
+void ossimPlanetAnimatedPointModel::setShowModelFlag(bool flag)
+{
+ theShowModelFlag = flag;
+}
+
+void ossimPlanetAnimatedPointModel::setPointModel(osg::Node* value)
+{
+ if(thePointModel.valid())
+ {
+ thePointModel->setUpdateCallback(0);
+ // need to test update callback to our animation update callback.
+ // thePointModel->getUpdateCallback();
+ }
+ thePointModel = value;
+ if(value)
+ {
+ value->setUpdateCallback(theAnimationPathCallback.get());
+ }
+}
+
+void ossimPlanetAnimatedPointModel::setTimeScale(ossim_float64 scale)
+{
+ theAnimationPathCallback->setTimeMultiplier(scale);
+}
+
+void ossimPlanetAnimatedPointModel::setTimeOffset(ossim_float64 offset)
+{
+ theAnimationPathCallback->setTimeOffset(offset);
+}
+
+void ossimPlanetAnimatedPointModel::traverse(osg::NodeVisitor& nv)
+{
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(theAnimationPath.valid()&&!theAnimationPath->geoRefModel())
+ {
+ if(layer()&&layer()->model())
+ {
+ theAnimationPath->setGeoRefModel(layer()->model());
+ // let's reset everything
+ setDirtyBit(COORDINATE_DIRTY);
+ setDirtyBit(COLOR_DIRTY);
+ }
+ }
+ if(isDirtyBitSet(COLOR_DIRTY))
+ {
+ updateColor();
+ }
+ if(isDirtyBitSet(COORDINATE_DIRTY))
+ {
+ updateCoordinates();
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ if(thePathVertices->size()>0)
+ {
+ if(nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
+ {
+ if(theShowPathFlag)
+ {
+ // draw the path
+ thePathMatrixTransform->accept(nv);
+ }
+ }
+ else
+ {
+ thePathMatrixTransform->accept(nv);
+ }
+ }
+ if(thePointModel.valid())
+ {
+ if(nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
+ {
+ if(theShowModelFlag)
+ {
+ thePointModel->accept(nv);
+ }
+ }
+ else
+ {
+ thePointModel->accept(nv);
+ }
+ }
+}
+
+void ossimPlanetAnimatedPointModel::stage()
+{
+ updateCoordinates();
+ updateColor();
+ setStagedFlag(true);
+}
+
+void ossimPlanetAnimatedPointModel::updateCoordinates()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theUpdateCoordinatesMutex);
+ if(theAnimationPath.valid())
+ {
+ ossimPlanetAnimationPath::PointList pointList;
+ theAnimationPath->generateWorldCoordinates(pointList);
+ bool updatePrimitiveSetFlag = false;
+ if(thePathVertices->size() != pointList.size())
+ {
+ updatePrimitiveSetFlag = true;
+ thePathVertices->resize(pointList.size());
+ }
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = pointList.size();
+ ossim_float64 normalizer = 1.0/static_cast<ossim_float64>(size);
+ osg::Vec3d theCenter;
+ if(pointList.size())
+ {
+ theCenter = pointList[0]*normalizer;
+ }
+ for(idx=1; idx < size; ++idx)
+ {
+ theCenter += pointList[idx]*normalizer;
+ }
+ osg::Matrixd m;
+ m.setTrans(theCenter);
+ thePathMatrixTransform->setMatrix(m);
+ for(idx=0; idx < size; ++idx)
+ {
+ osg::Vec3f localPoint = pointList[idx] - theCenter;
+ (*thePathVertices)[idx] = localPoint;
+ }
+ thePathGeometry->setVertexArray(thePathVertices.get());
+ if(updatePrimitiveSetFlag)
+ {
+ if(thePathGeometry->getNumPrimitiveSets() > 0)
+ {
+ thePathGeometry->setPrimitiveSet(0, new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, pointList.size()));
+ }
+ else
+ {
+ thePathGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,pointList.size()));
+ }
+ }
+
+ thePathGeode->dirtyBound();
+ thePathMatrixTransform->dirtyBound();
+ }
+
+ clearDirtyBit(COORDINATE_DIRTY);
+}
+
+void ossimPlanetAnimatedPointModel::updateColor()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theUpdateColorMutex);
+ if(thePathColor->size() != 1)
+ {
+ thePathColor->push_back(theAnimationPathColor);
+ }
+ else
+ {
+ (*thePathColor)[0] = theAnimationPathColor;
+ }
+ osg::StateSet* stateset = thePathGeometry->getOrCreateStateSet();
+ theLineWidth->setWidth(theAnimationPathLineThickness);
+ thePathGeometry->setColorArray(thePathColor.get());
+ thePathGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ stateset->setAttribute(theLineWidth.get());
+
+ thePathGeometry->setUseVertexBufferObjects(true);
+ thePathGeometry->setUseDisplayList(false);
+// thePathGeometry->setFastPathHint(true);
+ // for the path we will turn the lighting off
+ stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
+ stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+
+ clearDirtyBit(COLOR_DIRTY);
+}
+
+
+ossimPlanetAnimatedPointModel::PathCallback::PathCallback()
+:osg::AnimationPathCallback()
+{
+
+}
+ossimPlanetAnimatedPointModel::PathCallback::PathCallback(const PathCallback& apc,
+ const osg::CopyOp& copyop)
+:osg::AnimationPathCallback(apc, copyop)
+{
+}
+
+ossimPlanetAnimatedPointModel::PathCallback::PathCallback(osg::AnimationPath* ap,
+ double timeOffset,
+ double timeMultiplier)
+:osg::AnimationPathCallback(ap, timeOffset, timeMultiplier)
+{
+}
+
+void ossimPlanetAnimatedPointModel::PathCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+ ossimPlanetPointModel* pointModel = dynamic_cast<ossimPlanetPointModel*>(node);
+ ossimPlanetLsrSpaceTransform* lsrSpaceTransform = dynamic_cast<ossimPlanetLsrSpaceTransform*>(node);
+ if(pointModel||lsrSpaceTransform)
+ {
+ if (_animationPath.valid() &&
+ nv->getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR &&
+ nv->getFrameStamp())
+ {
+ double time = nv->getFrameStamp()->getSimulationTime();
+ // we might want to simulate both sim time and if real time by getting the first time to be real time
+ // but for now we will assume firstTime relative to 0 for sim time.
+ _latestTime = time;
+ _firstTime = 0.0;
+
+ if (!_pause)
+ {
+ // Only update _firstTime the first time, when its value is still DBL_MAX
+ //if (_firstTime==DBL_MAX) _firstTime = time;
+ osg::AnimationPath::ControlPoint cp;
+ if(pointModel) lsrSpaceTransform = pointModel->lsrSpace();
+ if (_animationPath->getInterpolatedControlPoint(getAnimationTime(),cp))
+ {
+ osg::Matrixd m;
+ cp.getMatrix(m);
+
+ lsrSpaceTransform->setMatrix(m);
+ }
+ }
+ }
+
+ // must call any nested node callbacks and continue subgraph traversal.
+ NodeCallback::traverse(node,nv);
+ }
+ else
+ {
+ osg::AnimationPathCallback::operator()(node, nv);
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetAnimationPath.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetAnimationPath.cpp
new file mode 100644
index 0000000..d40767c
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetAnimationPath.cpp
@@ -0,0 +1,407 @@
+#include <ossimPlanet/ossimPlanetAnimationPath.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <osg/io_utils>
+#include <fstream>
+#include <sstream>
+
+ossimPlanetAnimationPath::ossimPlanetAnimationPath()
+{
+}
+
+bool ossimPlanetAnimationPath::openAnimationPathByXmlDocument(const ossimFilename& animationFile)
+{
+ std::ifstream in(animationFile.c_str());
+ if(in.good())
+ {
+ return setAnimationPathByXmlDocument(in);
+ }
+
+ return false;
+}
+
+bool ossimPlanetAnimationPath::setAnimationPathByXmlDocument(const ossimString& xml)
+{
+ std::istringstream in(xml.c_str());
+ return setAnimationPathByXmlDocument(in);
+}
+
+bool ossimPlanetAnimationPath::setAnimationPathByXmlDocument(std::istream& xmlStream)
+{
+ bool result = false;
+ if(!xmlStream) return result;
+
+ ossimXmlDocument document;
+
+ if(document.read(xmlStream))
+ {
+ result = setAnimationPathByXmlNode(document.getRoot());
+ }
+
+ return result;
+}
+
+bool ossimPlanetAnimationPath::openAnimationPathByXmlNode(const ossimFilename& animationFile)
+{
+ std::ifstream in(animationFile.c_str());
+ if(in.good())
+ {
+ return setAnimationPathByXmlNode(in);
+ }
+
+ return false;
+}
+
+bool ossimPlanetAnimationPath::setAnimationPathByXmlNode(const ossimString& xml)
+{
+ std::istringstream in(xml.c_str());
+ return setAnimationPathByXmlNode(in);
+}
+
+bool ossimPlanetAnimationPath::setAnimationPathByXmlNode(std::istream& xmlStream)
+{
+ bool result = false;
+ if(!xmlStream) return result;
+
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+
+ if(node->read(xmlStream))
+ {
+ result = setAnimationPathByXmlNode(node.get());
+ }
+
+ return result;
+}
+
+
+ossimXmlNode* ossimPlanetAnimationPath::saveXml()const
+{
+ ossimXmlNode* root = new ossimXmlNode;
+ ossimXmlNode* coordinates = new ossimXmlNode;
+ ossimXmlNode* path = new ossimXmlNode;
+ root->setTag("AnimationPath");
+ path->setTag("GeospatialPath");
+ coordinates->setTag("coordinates");
+ path->setAttribute("timeUnit", "seconds", true);
+ path->setAttribute("positionType", "latlonhgt", true);
+ path->setAttribute("orientationType", "lsrhpr", true);
+
+ path->addChildNode(coordinates);
+
+ std::ostringstream coordinateList;
+
+ root->addChildNode(path);
+
+ TimeTupleMap::iterator iter = thePath->timeTupleMap().begin();
+ TimeTupleMap::iterator endIter = thePath->timeTupleMap().end();
+ while(iter!=endIter)
+ {
+ coordinateList << iter->first
+ << "," << iter->second.position()[0]
+ << "," << iter->second.position()[1]
+ << "," << iter->second.position()[2]
+ << "," << iter->second.orientation()[0]
+ << "," << iter->second.orientation()[1]
+ << "," << iter->second.orientation()[2]
+ << "," << iter->second.scale()[0]
+ << "," << iter->second.scale()[1]
+ << "," << iter->second.scale()[2]
+ << " \n";
+ ++iter;
+ }
+ coordinates->setText(coordinateList.str());
+
+ return root;
+}
+
+bool ossimPlanetAnimationPath::setAnimationPathByXmlNode(ossimRefPtr<ossimXmlNode> pathNode)
+{
+ bool result = true;
+ thePath = new GeospatialPath();
+ if((pathNode->getTag() == "AnimationPath"))
+ {
+ ossimRefPtr<ossimXmlNode> path = pathNode->findFirstNode("GeospatialPath");
+ ossimRefPtr<ossimXmlNode> coordinates = pathNode->findFirstNode("GeospatialPath/coordinates");
+ if(coordinates.valid()&&path.valid())
+ {
+ ossimString timeUnit = path->getAttributeValue("timeUnit");
+ ossimString positionType = path->getAttributeValue("positionType");
+ ossimString orientationType = path->getAttributeValue("orientationType");
+
+ // only support for now decoding relative time in seconds
+ // and lsr space type position and orientation.
+ //
+ if((timeUnit == "seconds") &&
+ (positionType == "latlonhgt") &&
+ (orientationType == "lsrhpr"))
+ {
+ std::istringstream in(coordinates->getText());
+ ossimString tuple = "";
+ while(in.good())
+ {
+ in >> ossim::skipws;
+ tuple = "";
+ while(in.good()&&!ossim::isWhiteSpace(in.peek()))
+ {
+ tuple += static_cast<char>(in.get());
+ }
+ if(!tuple.empty())
+ {
+ std::vector<ossimString> tupleValues;
+ tuple.split(tupleValues, ",");
+ if(tupleValues.size() >= 4) //time and position only
+ {
+ double t = tupleValues[0].toDouble(); // time
+ osg::Vec3d pos(tupleValues[1].toDouble(), // positional
+ tupleValues[2].toDouble(),
+ tupleValues[3].toDouble());
+ osg::Vec3d orient(0.0,0.0,0.0); // identity
+ osg::Vec3d scale(1.0,1.0,1.0); // identity
+ if(tupleValues.size() >= 7) // add orientation
+ {
+ orient = osg::Vec3d(tupleValues[4].toDouble(),
+ tupleValues[5].toDouble(),
+ tupleValues[6].toDouble());
+ if(tupleValues.size()==10) // add scale to the animation path
+ {
+ scale = osg::Vec3d(tupleValues[7].toDouble(),
+ tupleValues[8].toDouble(),
+ tupleValues[9].toDouble());
+ }
+ }
+ thePath->timeTupleMap().insert(std::make_pair(t, Tuple(pos, orient, scale)));
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ }
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ else
+ {
+ result = false;
+ }
+
+ return result;
+}
+
+bool ossimPlanetAnimationPath::getInterpolatedControlPoint(double time,
+ osg::AnimationPath::ControlPoint& controlPoint) const
+{
+ if(!theModel.valid()||!thePath.valid()||thePath->timeTupleMap().empty()) return false;
+
+ time = adjustTime(time);
+ TimeTupleMap::const_iterator second = thePath->timeTupleMap().lower_bound(time);
+ if (second==thePath->timeTupleMap().begin())
+ {
+ // use the model to create the control point in osg form
+ //
+ osg::Quat q;
+ osg::Vec3d pos;
+ osg::Matrixd m;
+
+ lsrMatrix(m, second->second);
+ m = osg::Matrixd::scale(second->second.scale())*m;
+ q.set(m);
+ pos.set(m(3,0), m(3,1), m(3,2));
+ controlPoint = ControlPoint(pos, q);
+ }
+ else if (second!=thePath->timeTupleMap().end())
+ {
+ TimeTupleMap::const_iterator first = second;
+ --first;
+
+ // we have both a lower bound and the next item.
+
+ // delta_time = second.time - first.time
+ double delta_time = second->first - first->first;
+
+ if (delta_time==0.0)
+ {
+ osg::Quat q;
+ osg::Vec3d pos;
+ osg::Matrixd m;
+
+ lsrMatrix(m, first->second);
+ q.set(m);
+ pos.set(m(3,0), m(3,1), m(3,2));
+ controlPoint = ControlPoint(pos, q);
+ }
+ else
+ {
+ ControlPoint one, two;
+ osg::Quat q;
+ osg::Vec3d pos;
+ osg::Matrixd m;
+
+ lsrMatrix(m, first->second);
+ q.set(m);
+ pos.set(m(3,0), m(3,1), m(3,2));
+ one = ControlPoint(pos, q);
+ lsrMatrix(m, second->second);
+ q.set(m);
+ pos.set(m(3,0), m(3,1), m(3,2));
+ two = ControlPoint(pos, q);
+ controlPoint.interpolate((time - first->first)/delta_time,
+ one,
+ two);
+ }
+ }
+ else // (second==_timeControlPointMap.end())
+ {
+ osg::Quat q;
+ osg::Vec3d pos;
+ osg::Matrixd m;
+
+ lsrMatrix(m, thePath->timeTupleMap().rbegin()->second);
+ q.set(m);
+ pos.set(m(3,0), m(3,1), m(3,2));
+ controlPoint = ControlPoint(pos, q);
+ }
+ return true;
+}
+
+double ossimPlanetAnimationPath::adjustTime(double t)const
+{
+ double time = t;
+ switch(_loopMode)
+ {
+ case(SWING):
+ {
+ double modulated_time = (time - thePath->firstTime())/(thePath->period()*2.0);
+ double fraction_part = modulated_time - floor(modulated_time);
+ if (fraction_part>0.5) fraction_part = 1.0-fraction_part;
+
+ time = thePath->firstTime()+(fraction_part*2.0) * thePath->period();
+ break;
+ }
+ case(LOOP):
+ {
+ double modulated_time = (time - thePath->firstTime())/thePath->period();
+ double fraction_part = modulated_time - floor(modulated_time);
+ time = thePath->firstTime()+fraction_part * thePath->period();
+ break;
+ }
+ case(NO_LOOPING):
+ // no need to modulate the time.
+ break;
+ }
+
+ return time;
+}
+
+void ossimPlanetAnimationPath::lsrMatrix(osg::Matrixd& result,
+ const Tuple& tuple)const
+{
+ osg::Vec3d position = tuple.position();
+ theModel->mslToEllipsoidal(position); // adjust to ellipsoidal location
+ theModel->orientationLsrMatrix(result,
+ position,
+ tuple.orientation()[0],
+ tuple.orientation()[1],
+ tuple.orientation()[2]);
+ result = osg::Matrixd::scale(tuple.scale())*result;
+
+}
+
+bool ossimPlanetAnimationPath::generateWorldCoordinates(PointList& worldPoints)const
+{
+ if(!theModel.valid()&&thePath.valid())
+ {
+ return false;
+ }
+ TimeTupleMap::const_iterator iter = thePath->timeTupleMap().begin();
+ TimeTupleMap::const_iterator endIter = thePath->timeTupleMap().end();
+
+ while(iter!=endIter)
+ {
+ osg::Vec3d worldPoint;
+ // convert Lat lon Height to world point
+ //
+ osg::Vec3d position(iter->second.position());
+
+ // shift to ellipsoid
+ //
+ theModel->mslToEllipsoidal(position);
+ theModel->forward(position, worldPoint);
+ worldPoints.push_back(worldPoint);
+
+ ++iter;
+ }
+
+ return true;
+}
+
+bool ossimPlanetAnimationPath::generateModelCoordinates(PointList& modelPoints)const
+{
+ TimeTupleMap::const_iterator iter = thePath->timeTupleMap().begin();
+ TimeTupleMap::const_iterator endIter = thePath->timeTupleMap().end();
+
+ while(iter!=endIter)
+ {
+ modelPoints.push_back(iter->second.position());
+ ++iter;
+ }
+
+ return true;
+}
+
+bool ossimPlanetAnimationPath::moveToLocationLatLon(const osg::Vec2d& llh)
+{
+ PointList worldPoints;
+ bool result = false;
+ if(generateWorldCoordinates(worldPoints)&&
+ (worldPoints.size()))
+ {
+ osg::Vec3d centerWorld;
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = worldPoints.size();
+ for(idx = 0; idx < size; ++idx)
+ {
+ centerWorld += worldPoints[idx];
+ }
+ centerWorld *= (1.0/(double)size);
+ osg::Vec3d centerWorldLlh;
+ theModel->xyzToLatLonHeight(centerWorld, centerWorldLlh);
+ osg::Vec3d centerDistinationLlh(llh[0],
+ llh[1],
+ centerWorldLlh[2]);
+
+ osg::Matrixd lsrSourceMatrix;
+ osg::Matrixd lsrDestinationMatrix;
+ theModel->lsrMatrix(centerWorldLlh, lsrSourceMatrix);
+ theModel->lsrMatrix(centerDistinationLlh, lsrDestinationMatrix);
+
+ osg::Matrixd sourceInvert(osg::Matrixd::inverse(lsrSourceMatrix));
+
+ for(idx = 0; idx < size; ++idx)
+ {
+ osg::Vec3d relative = worldPoints[idx]*sourceInvert;
+ osg::Vec3d newPoint = relative*lsrDestinationMatrix;
+ worldPoints[idx] = newPoint;
+ }
+ TimeTupleMap::iterator iter = thePath->timeTupleMap().begin();
+ osg::Vec3d newModelPoint;
+ for(idx = 0; idx < size; ++idx)
+ {
+ theModel->xyzToLatLonHeight(worldPoints[idx], newModelPoint);
+ theModel->ellipsoidalToMsl(newModelPoint);
+ iter->second.setPosition(newModelPoint);
+ ++iter;
+ }
+ result = true;
+ }
+
+ return result;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetAnnotationLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetAnnotationLayer.cpp
new file mode 100644
index 0000000..c3d5817
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetAnnotationLayer.cpp
@@ -0,0 +1,246 @@
+#include <ossimPlanet/ossimPlanetAnnotationLayer.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetNodeRegistry.h>
+#include <osgUtil/IntersectVisitor>
+#include <algorithm>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <OpenThreads/ScopedLock>
+
+
+ossimPlanetAnnotationLayer::ossimPlanetAnnotationLayer()
+{
+ theStagingThreadQueue = new ossimPlanetOperationThreadQueue;
+ theUpdateThreadQueue = new ossimPlanetOperationThreadQueue;
+ theDefaultIconImage = new osg::Image;
+ theDefaultIconImage->allocateImage(32, 32, 1, GL_RGBA, GL_UNSIGNED_BYTE);
+ memset(theDefaultIconImage->data(), 255, theDefaultIconImage->getImageSizeInBytes());
+ theDefaultIconTexture = new osg::Texture2D;
+ theDefaultIconTexture->setImage(theDefaultIconImage.get());
+ theDefaultIconTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture2D::NEAREST);
+ theDefaultIconTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture2D::NEAREST);
+ theDefaultIconTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ theDefaultIconTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ theDefaultIconTexture->setWrap(osg::Texture2D::WRAP_R, osg::Texture2D::CLAMP_TO_EDGE);
+ theDefaultIconTexture->setDataVariance(osg::Object::STATIC);
+ theDefaultFont = osgText::readFontFile("fonts/arial.ttf");
+
+ //theDefaultIconTexture->setResizeNonPowerOfTwoHint(true);
+}
+
+ossimPlanetAnnotationLayer::~ossimPlanetAnnotationLayer()
+{
+ theStagingThreadQueue = 0;
+}
+
+void ossimPlanetAnnotationLayer::traverse(osg::NodeVisitor& nv)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGraphMutex);
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNodesToRemoveListMutex);
+ ossimPlanetNode::NodeListType::iterator iter = theNodesToRemoveList.begin();
+ while(iter != theNodesToRemoveList.end())
+ {
+ ossimPlanetNode::remove((*iter).get());
+ ++iter;
+ }
+ theNodesToRemoveList.clear();
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ ossimPlanetLayer::traverse(nv);
+}
+
+void ossimPlanetAnnotationLayer::execute(const ossimPlanetAction& action)
+{
+ std::string command = action.command();
+ const ossimPlanetXmlAction* xmlAction = action.toXmlAction();
+ if(command == "Add")
+ {
+ // we will use the add action to get the child
+ if(xmlAction&&xmlAction->xmlNode().valid())
+ {
+ const ossimXmlNode::ChildListType& children = xmlAction->xmlNode()->getChildNodes();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < children.size(); ++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ ossimString parentId = children[idx]->getAttributeValue("parentId");
+ ossimString id = children[idx]->getChildTextValue("id");
+ if(!id.empty())
+ {
+ ossimPlanetLayerNameIdSearchVisitor nv("", id);
+ accept(nv);
+ if(nv.node().get())
+ {
+ // already an id exists with that value so we return and don't add
+ return;
+ }
+ }
+ osg::ref_ptr<ossimPlanetNode> layerNode;
+ if(tag != "Group")
+ {
+ layerNode = ossimPlanetNodeRegistry::instance()->create(tag);
+ }
+ if(!layerNode.valid()&&(tag == "Group"))
+ {
+ if(children[idx]->getAttributeValue("groupType")=="feature")
+ {
+ layerNode = new ossimPlanetAnnotationGroupNode();
+ }
+ }
+ if(layerNode.valid())
+ {
+ osg::ref_ptr<ossimPlanetXmlAction> tempAction = xmlAction->duplicateChildAndMaintainAction(idx);
+ tempAction->setCommand("Set");
+ layerNode->setLayer(this);
+ layerNode->execute(*tempAction);
+ }
+ osg::ref_ptr<ossimPlanetAnnotationLayerNode> annotationNode = dynamic_cast<ossimPlanetAnnotationLayerNode*>(layerNode.get());
+ if(annotationNode.valid())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGraphMutex);
+ if(!annotationNode->isStaged())
+ {
+ theStagingThreadQueue->add(new ossimPlanetAnnotationLayer::Stager(annotationNode.get()));
+ }
+ ossimPlanetNode* parentNode=0;
+ if(!parentId.empty())
+ {
+ ossimPlanetLayerNameIdSearchVisitor nv("", parentId);
+ accept(nv);
+ parentNode = dynamic_cast<ossimPlanetNode*>(nv.node().get());
+ }
+
+ if(parentNode)
+ {
+ parentNode->addChild(annotationNode.get());
+ }
+ else
+ {
+ addChild(annotationNode.get());
+ }
+ setRedrawFlag(true);
+ }
+ }
+ }
+ }
+ else if(command == "Set")
+ {
+ ossimString actionId = xmlAction->id();
+ if(!actionId.empty())
+ {
+ ossimPlanetLayerNameIdSearchVisitor idSearch;
+ idSearch.setId(actionId);
+ accept(idSearch);
+ ossimPlanetNode* node = dynamic_cast<ossimPlanetNode*>(idSearch.node().get());
+ if(node)
+ {
+ node->execute(action);
+ }
+ }
+ else
+ {
+ ossim_uint32 idx;
+ const ossimXmlNode::ChildListType& children = xmlAction->xmlNode()->getChildNodes();
+ for(idx = 0; idx < children.size(); ++idx)
+ {
+ ossimString id;
+ if(children[idx]->getAttributeValue(id, "id"))
+ {
+ ossimPlanetLayerNameIdSearchVisitor idSearch;
+ idSearch.setId(id);
+ accept(idSearch);
+ ossimPlanetNode* node = dynamic_cast<ossimPlanetNode*>(idSearch.node().get());
+ if(node)
+ {
+ osg::ref_ptr<ossimPlanetXmlAction> tempAction = xmlAction->duplicateChildAndMaintainAction(idx);
+ tempAction->setCommand("Set");
+ node->execute(*tempAction);
+ }
+ }
+ }
+ }
+ }
+ else if(command == "Get")
+ {
+ }
+ else if(command == "Remove")
+ {
+ ossimString id;
+ ossimString name;
+ // do short form
+ // <Remove id="">
+ if(!xmlAction->hasChildren())
+ {
+ ossimString id = xmlAction->id();
+ ossimString name = xmlAction->name();
+ if(!id.empty()||!name.empty())
+ {
+ removeByNameAndId(name, id);
+ }
+ }
+ else
+ {
+ const ossimXmlNode::ChildListType& children = xmlAction->xmlNode()->getChildNodes();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < children.size();++idx)
+ {
+ name = children[idx]->getAttributeValue("name");
+ id = children[idx]->getAttributeValue("id");
+ if(name.empty()&&id.empty())
+ {
+ name = children[idx]->getChildTextValue("name");
+ id = children[idx]->getChildTextValue("id");
+ }
+ if(!name.empty()||!id.empty())
+ {
+ removeByNameAndId(name, id);
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetAnnotationLayer::removeByNameAndId(const ossimString& name, const ossimString& id)
+{
+ ossimPlanetLayerNameIdSearchVisitor nv(name, id);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGraphMutex);
+ accept(nv);
+ ossimPlanetNode* node = dynamic_cast<ossimPlanetNode*>(nv.node().get());
+ if(node)
+ {
+ needsRemoving(node);
+ }
+}
+
+void ossimPlanetAnnotationLayer::nodeAdded(osg::Node* /* node */)
+{
+}
+
+void ossimPlanetAnnotationLayer::nodeRemoved(osg::Node* /* node */)
+{
+}
+
+void ossimPlanetAnnotationLayer::needsRemoving(osg::Node* node)
+{
+ ossimPlanetNode* pNode = dynamic_cast<ossimPlanetNode*>(node);
+ if(pNode)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNodesToRemoveListMutex);
+ // keep it around for next update removal
+ theNodesToRemoveList.push_back(pNode);
+ }
+ setRedrawFlag(true);
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetAnnotationLayerNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetAnnotationLayerNode.cpp
new file mode 100644
index 0000000..70f6ea2
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetAnnotationLayerNode.cpp
@@ -0,0 +1,557 @@
+#include <ossimPlanet/ossimPlanetAnnotationLayerNode.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetBillboardIcon.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetAnnotationLayer.h>
+#include <ossimPlanet/ossimPlanetIconGeom.h>
+#include <osgUtil/IntersectVisitor>
+#include <sstream>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+static inline void annotationAdjustHeight(osg::Vec3d& input,
+ ossimPlanetAltitudeMode mode,
+ ossimPlanetGeoRefModel* modelTransform)
+{
+ switch(mode)
+ {
+ case ossimPlanetAltitudeMode_CLAMP_TO_GROUND:
+ {
+ input[2] = modelTransform->getHeightAboveEllipsoid(input[0], input[1]);
+ break;
+ }
+ case ossimPlanetAltitudeMode_RELATIVE_TO_GROUND:
+ {
+ input[2]+=modelTransform->getHeightAboveEllipsoid(input[0], input[1]);
+ break;
+ }
+ case ossimPlanetAltitudeMode_ABSOLUTE:
+ {
+ input[2] += modelTransform->getGeoidOffset(input[0], input[2]);
+ break;
+ }
+ default:
+ {
+ input[2] = modelTransform->getHeightAboveEllipsoid(input[0], input[1]);
+ break;
+ }
+ }
+}
+
+class AnnotationUpdater : public ossimPlanetOperation
+ {
+ public:
+ AnnotationUpdater()
+ {}
+ AnnotationUpdater(ossimPlanetAnnotationPlacemark* placemark)
+ :theNode(placemark)
+ {
+
+ }
+ virtual void run()
+ {
+ theNode->update();
+ }
+ protected:
+ osg::ref_ptr<ossimPlanetAnnotationPlacemark> theNode;
+ };
+
+
+
+ossimPlanetAnnotationLayerNode::ossimPlanetAnnotationLayerNode()
+:ossimPlanetNode(),
+theDirtyBit(NOT_DIRTY),
+theStagedFlag(false)
+{
+}
+
+void ossimPlanetAnnotationLayerNode::traverse(osg::NodeVisitor& nv)
+{
+ ossimPlanetNode::traverse(nv);
+}
+
+
+void ossimPlanetAnnotationLayerNode::execute(const ossimPlanetAction& action)
+{
+ ossimPlanetNode::execute(action);
+}
+
+ossimPlanetAnnotationPlacemark::ossimPlanetAnnotationPlacemark()
+:ossimPlanetAnnotationLayerNode(),
+theLabelStyle(new ossimPlanetAnnotationLabelStyle)
+{
+}
+
+ossimPlanetAnnotationPlacemark::ossimPlanetAnnotationPlacemark(const osg::Vec3d& location,
+ ossimPlanetAltitudeMode altitudeMode,
+ const ossimString& nameStr,
+ const ossimString& descriptionStr)
+:ossimPlanetAnnotationLayerNode(),
+theLabelStyle(new ossimPlanetAnnotationLabelStyle)
+{
+ setName(nameStr);
+ setDescription(descriptionStr);
+ ossimPlanetAnnotationPoint* point = new ossimPlanetAnnotationPoint(location);
+ point->setAltitudeMode(altitudeMode);
+ setGeometry(point);
+}
+
+void ossimPlanetAnnotationPlacemark::traverse(osg::NodeVisitor& nv)
+{
+ if(!enableFlag()) return;
+ if(!isStaged())
+ {
+ return;
+ }
+ bool needRedraw = false;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theUpdateMutex);
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(isDirtyBitSet(LABEL_DIRTY)&&theLabel.valid())
+ {
+ needRedraw = true;
+ if(theLabel.valid())
+ {
+ theLabel->setText(name().c_str());
+ }
+ clearDirtyBit(LABEL_DIRTY);
+ }
+ if(isDirtyBitSet(COLOR_DIRTY))
+ {
+ if(theLabelStyle.valid()&&theLabel.valid())
+ {
+ needRedraw = true;
+ if(theLabelStyle->colorMode() == ossimPlanetAnnotationColorMode_NORMAL)
+ {
+ theLabel->setColor(theLabelStyle->color());
+ }
+ else
+ {
+ theLabel->setColor(osg::Vec4d((ossim_float64)rand()/(ossim_float64)RAND_MAX,
+ (ossim_float64)rand()/(ossim_float64)RAND_MAX,
+ (ossim_float64)rand()/(ossim_float64)RAND_MAX,
+ theLabel->getColor()[3]));
+ }
+ }
+ clearDirtyBit(COLOR_DIRTY);
+ }
+ if(theExpireTime.valid())
+ {
+ if(theExpireTime->hasExpired())
+ {
+ if(theLayer)
+ {
+ theLayer->needsRemoving(this);
+ }
+ }
+ needRedraw = true;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ if(theExpireTime.valid())
+ {
+ setRedrawFlag(true);
+ }
+ osg::ref_ptr<ossimPlanetAnnotationGeometry> geom = geometry();
+ if(geom.valid())
+ {
+ geom->traverse(nv);
+ }
+ ossimPlanetAnnotationLayerNode::traverse(nv);
+ if(needRedraw) setRedrawFlag(true);
+}
+
+
+void ossimPlanetAnnotationPlacemark::execute(const ossimPlanetAction& action)
+{
+ std::string command = action.command();
+ const ossimPlanetXmlAction* xmlAction = action.toXmlAction();
+ ossimPlanetAnnotationLayerNode::execute(action);
+ if(command == "Set")
+ {
+ bool coordinateUpdating = false;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theUpdateMutex);
+ if(xmlAction&&xmlAction->xmlNode().valid())
+ {
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& childNodes = xmlAction->xmlNode()->getChildNodes();
+ const ossimXmlNode::ChildListType* properties = 0;
+ // at this point we should just have a single object in the first child of the set
+ //
+ if(childNodes.size() > 0)
+ {
+ if((childNodes[0]->getTag() == "Placemark")||
+ (childNodes[0]->getTag() == "Object"))
+ {
+ properties = &(childNodes[0]->getChildNodes());
+ }
+ else
+ {
+ properties = &childNodes;
+ }
+ }
+ if(!properties) return;
+ if(properties->size()==0)
+ {
+ properties = &childNodes; // we have direct properties first
+ }
+ for(idx = 0;idx<properties->size();++idx)
+ {
+ ossimString tag = (*properties)[idx]->getTag();
+ if(tag == "Style")
+ {
+ const ossimXmlNode::ChildListType& childStyleNodes = (*properties)[idx]->getChildNodes();
+ ossim_uint32 styleIdx = 0;
+ for(styleIdx = 0;styleIdx<childStyleNodes.size();++styleIdx)
+ {
+ if(childStyleNodes[styleIdx]->getTag() == "LabelStyle")
+ {
+ ossimString color = childStyleNodes[styleIdx]->getChildTextValue("color").trim();
+ ossimString colorMode = childStyleNodes[styleIdx]->getChildTextValue("colorMode").trim();
+ ossimString scale = childStyleNodes[styleIdx]->getChildTextValue("scale").trim();
+ if(!color.empty())
+ {
+ std::vector<ossimString> colorValues;
+ color.split(colorValues, " ");
+ if(colorValues.size() == 4)
+ {
+ theLabelStyle->setColor(osg::Vec4d(colorValues[0].toDouble(),
+ colorValues[1].toDouble(),
+ colorValues[2].toDouble(),
+ colorValues[3].toDouble()));
+ }
+ else if(colorValues.size() == 3)
+ {
+ theLabelStyle->setColor(osg::Vec4d(colorValues[0].toDouble(),
+ colorValues[1].toDouble(),
+ colorValues[2].toDouble(),
+ 1.0));
+ }
+ else if(colorValues.size() == 1)
+ {
+ theLabelStyle->setColor(osg::Vec4d(colorValues[0].toDouble(),
+ colorValues[0].toDouble(),
+ colorValues[0].toDouble(),
+ 1.0));
+ }
+ }
+ if(!colorMode.empty())
+ {
+ if(colorMode == "random")
+ {
+ theLabelStyle->setColorMode(ossimPlanetAnnotationColorMode_RANDOM);
+ }
+ else if(colorMode == "normal")
+ {
+ theLabelStyle->setColorMode(ossimPlanetAnnotationColorMode_NORMAL);
+ }
+ }
+ }
+ }
+ setDirtyBit(COLOR_DIRTY);
+ setRedrawFlag(true);
+ }
+ else if(tag == "color")
+ {
+ ossimString color = (*properties)[idx]->getText();
+ std::vector<ossimString> colorValues;
+ color.split(colorValues, " ");
+ if(colorValues.size() == 4)
+ {
+ theLabelStyle->setColor(osg::Vec4d(colorValues[0].toDouble(),
+ colorValues[1].toDouble(),
+ colorValues[2].toDouble(),
+ colorValues[3].toDouble()));
+ }
+ else if(colorValues.size() == 3)
+ {
+ theLabelStyle->setColor(osg::Vec4d(colorValues[0].toDouble(),
+ colorValues[1].toDouble(),
+ colorValues[2].toDouble(),
+ 1.0));
+ }
+ else if(colorValues.size() == 1)
+ {
+ theLabelStyle->setColor(osg::Vec4d(colorValues[0].toDouble(),
+ colorValues[0].toDouble(),
+ colorValues[0].toDouble(),
+ 1.0));
+ }
+ setDirtyBit(COLOR_DIRTY);
+ setRedrawFlag(true);
+ }
+ else if(tag == "description")
+ {
+ setDescription((*properties)[idx]->getText());
+ }
+ else if(tag == "name")
+ {
+ setName((*properties)[idx]->getText());
+ setDirtyBit(LABEL_DIRTY);
+ setRedrawFlag(true);
+ }
+ else if(tag == "coordinates")
+ {
+ ossimPlanetAnnotationPoint* pointGeom = dynamic_cast<ossimPlanetAnnotationPoint*>(theGeometry.get());
+ if(pointGeom)
+ {
+ ossimString coordinates = (*properties)[idx]->getText().trim();
+ if(!coordinates.empty())
+ {
+ double lon=0.0, lat=0.0, hgt=0.0;
+ ossimString coordinateStr;
+ std::stringstream in(coordinates);
+ in >> coordinateStr;
+ std::vector<ossimString> splitArray;
+ coordinateStr.split(splitArray, ",");
+ if(splitArray.size() >1)
+ {
+ lon = splitArray[0].toDouble();
+ lat = splitArray[1].toDouble();
+ if(splitArray.size() > 2)
+ {
+ hgt = splitArray[2].toDouble();
+ }
+ }
+ coordinateUpdating = true;
+ setDirtyBit(COORDINATE_DIRTY);
+ pointGeom->setCoordinate(osg::Vec3d(lat,lon,hgt));
+ setRedrawFlag(true);
+ }
+ }
+ }
+ else if(tag == "Point")
+ {
+ coordinateUpdating = true;
+ ossimPlanetAnnotationPoint* pointGeom = dynamic_cast<ossimPlanetAnnotationPoint*>(theGeometry.get());
+ if(!pointGeom)
+ {
+ pointGeom = new ossimPlanetAnnotationPoint;
+ theGeometry = pointGeom;
+ }
+ ossimString coordinates = (*properties)[idx]->getChildTextValue("coordinates").trim();
+ ossimString altitudeMode = (*properties)[idx]->getChildTextValue("altitudeMode").trim();
+ ossimString extrudeFlag = (*properties)[idx]->getChildTextValue("extrude").trim();
+ if(!coordinates.empty())
+ {
+ double lon=0.0, lat=0.0, hgt=0.0;
+ ossimString coordinateStr;
+ std::stringstream in(coordinates);
+ in >> coordinateStr;
+ std::vector<ossimString> splitArray;
+ coordinateStr.split(splitArray, ",");
+ if(splitArray.size() >1)
+ {
+ lon = splitArray[0].toDouble();
+ lat = splitArray[1].toDouble();
+ if(splitArray.size() > 2)
+ {
+ hgt = splitArray[2].toDouble();
+ }
+ }
+ pointGeom->setCoordinate(osg::Vec3d(lat,lon,hgt));
+ }
+ ossimPlanetAltitudeMode mode = ossimPlanetAltitudeMode_NONE;
+ if(!altitudeMode.empty())
+ {
+ if(altitudeMode.contains("clamp"))
+ {
+ mode = ossimPlanetAltitudeMode_CLAMP_TO_GROUND;
+ }
+ else if(altitudeMode.contains("relative"))
+ {
+ mode = ossimPlanetAltitudeMode_RELATIVE_TO_GROUND;
+ }
+ else if(altitudeMode.contains("absolute"))
+ {
+ mode = ossimPlanetAltitudeMode_ABSOLUTE;
+ }
+ }
+ pointGeom->setAltitudeMode(mode);
+ if(extrudeFlag == "extrude")
+ {
+ pointGeom->setExtrudeFlag(extrudeFlag.toBool());
+ }
+ setDirtyBit(COORDINATE_DIRTY);
+ setRedrawFlag(true);
+ }
+ else if(tag == "ExpireDuration")
+ {
+ ossimString value = (*properties)[idx]->getAttributeValue("value").trim();
+ ossimString units = (*properties)[idx]->getAttributeValue("units").trim();
+ if(!value.empty())
+ {
+ ossimPlanetAnnotationExpireDuration* duration = new ossimPlanetAnnotationExpireDuration;
+ duration->setDuration(value.toDouble());
+ theExpireTime = duration;
+ // right now we ignore units. Will add that support later
+ }
+ else
+ {
+ theExpireTime = 0;
+ }
+ }
+ }
+ }
+ if(isDirtyBitSet(COORDINATE_DIRTY)&&theStagedFlag)
+ {
+ if(geometry()->asPoint())
+ {
+ update();
+ }
+ else
+ {
+ ossimPlanetAnnotationLayer* l = dynamic_cast<ossimPlanetAnnotationLayer*>(layer());
+ if(l)
+ {
+ l->updateThreadQueue()->add(new AnnotationUpdater(this));
+ }
+ else
+ {
+ update();
+ }
+ }
+ }
+ setRedrawFlag(true);
+ }
+}
+
+void ossimPlanetAnnotationPlacemark::update()
+{
+ if(!layer()) return;
+ if(!theGeometry.valid()) return;
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = layer()->model();
+
+ if(isDirtyBitSet(ossimPlanetAnnotationLayerNode::COORDINATE_DIRTY))
+ {
+ if(model.valid())
+ {
+ osg::ref_ptr<ossimPlanetAnnotationPoint> point = geometry()->asPoint();
+ if(point.valid())
+ {
+ osg::Matrixd localToWorld;
+ osg::Vec3d modelCoordinate;
+ osg::Vec3d normal;
+ osg::Vec3d localNormal;
+ osg::Vec3d coordinate = point->coordinate();
+ annotationAdjustHeight(coordinate,
+ point->altitudeMode(),
+ model.get());
+ model->forward(coordinate, modelCoordinate);
+ normal = modelCoordinate;
+ normal.normalize();
+ point->setModelCoordinate(modelCoordinate);
+ model->lsrMatrix(coordinate, localToWorld);
+ osg::ref_ptr<osg::MatrixTransform> m = point->matrixTransform();
+ if(clusterCull().valid())
+ {
+ osg::Vec3d localNormal = osg::Matrixd::transform3x3(localToWorld, normal);
+ clusterCull()->set(osg::Vec3d(0.0,0.0,0.0), localNormal, 0.0, -1.0);
+ }
+ m->setMatrix(localToWorld);
+ }
+ }
+ clearDirtyBit(ossimPlanetAnnotationLayerNode::COORDINATE_DIRTY);
+ setRedrawFlag(true);
+ }
+}
+
+void ossimPlanetAnnotationPlacemark::stage()
+{
+
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = layer()->model();
+ ossimPlanetAnnotationLayer* annotationLayer = dynamic_cast<ossimPlanetAnnotationLayer*>(theLayer);
+ if(annotationLayer)
+ {
+ if(annotationLayer->planet())
+ {
+ if(model.valid()&&geometry().valid())
+ {
+ osg::ref_ptr<ossimPlanetAnnotationPoint> point = geometry()->asPoint();
+ if(point.valid())
+ {
+ osg::Matrixd localToWorld;
+ osg::Vec3d modelCoordinate;
+ osg::Vec3d normal;
+ osg::Vec3d localNormal;
+ osg::Vec3d coordinate = point->coordinate();
+ annotationAdjustHeight(coordinate,
+ point->altitudeMode(),
+ model.get());
+ model->forward(coordinate, modelCoordinate);
+ normal = modelCoordinate;
+ normal.normalize();
+ point->setModelCoordinate(modelCoordinate);
+ model->lsrMatrix(coordinate, localToWorld);
+ osg::MatrixTransform* m = new osg::MatrixTransform;
+ m->setMatrix(localToWorld);
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theUpdateMutex);
+ osg::Vec3d localNormal = osg::Matrixd::transform3x3(localToWorld, normal);
+ theLabel = new ossimPlanetFadeText();
+ theLabel->setText(name());
+ theLabel->setFont(annotationLayer->defaultFont().get());
+ theLabel->setBackdropType(osgText::Text::OUTLINE);
+ osg::Vec3d textEcef(0.0,0.0,0.0);
+ theLabel->setPosition(textEcef);
+ theLabel->setCharacterSize(30000.0f/model->getNormalizationScale());
+ theLabel->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
+ theLabel->setAutoRotateToScreen(true);
+ theLabel->setAlignment(osgText::Text::CENTER_BOTTOM);
+ theClusterCull = new osg::ClusterCullingCallback(textEcef, localNormal, 0.0);
+ theLabel->setClusterCullingCallback(theClusterCull.get());
+ theLabelGeode = new ossimPlanetAnnotationTextGeode(this, theLabel.get());
+ theLabelGeode->addDrawable(theLabel.get());
+ theLabelGeode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+ m->addChild(theLabelGeode.get());
+ if(theLabelStyle->colorMode() == ossimPlanetAnnotationColorMode_NORMAL)
+ {
+ theLabel->setColor(theLabelStyle->color());
+ }
+ else
+ {
+ theLabel->setColor(osg::Vec4d((ossim_float64)rand()/(ossim_float64)RAND_MAX,
+ (ossim_float64)rand()/(ossim_float64)RAND_MAX,
+ (ossim_float64)rand()/(ossim_float64)RAND_MAX,
+ theLabel->getColor()[3]));
+ }
+ }
+// ossimPlanetBillboardIcon* icon = new ossimPlanetBillboardIcon;
+// ossimPlanetIconGeom* geom = new ossimPlanetIconGeom;
+// if(annotationLayer)
+// {
+// geom->setTexture(annotationLayer->defaultIconTexture().get());
+// }
+// icon->setGeom(geom);
+// m->addChild(icon);
+ point->setMatrixTransform(m);
+ if(!lookAt().valid())
+ {
+ setLookAt(new ossimPlanetLookAt(coordinate[0],
+ coordinate[1],
+ coordinate[2],
+ 0, 45, 0, 5000));
+ }
+ }
+ }
+ }
+ }
+ if(theExpireTime.valid())
+ {
+ theExpireTime->initTimeStamp();
+ }
+ clearDirtyBit(ALL_DIRTY);
+ setStagedFlag(true);
+}
+
+void ossimPlanetAnnotationPlacemark::setName(const ossimString& name)
+{
+ ossimPlanetAnnotationLayerNode::setName(name);
+ setDirtyBit(LABEL_DIRTY);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetApi.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetApi.cpp
new file mode 100644
index 0000000..e62ca2d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetApi.cpp
@@ -0,0 +1,1135 @@
+#include <ossimPlanet/ossimPlanetApi.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <ossimPlanet/ossimPlanetLayerRegistry.h>
+#include <ossim/base/ossimMatrix4x4.h>
+#include <ossim/base/ossimTraceManager.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/plugin/ossimSharedPluginRegistry.h>
+#include <ossim/base/ossimGeoidManager.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimGeoidEgm96.h>
+#include <ossim/base/ossimGeoidNgs.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/init/ossimInit.h>
+#include <osgUtil/SceneView>
+#include <osgViewer/Viewer>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+#include <ossimPlanet/ossimPlanetManipulator.h>
+#include <osgGA/TerrainManipulator>
+#include <osgGA/TerrainManipulator>
+#include <osgGA/KeySwitchMatrixManipulator>
+#include <osgDB/Registry>
+#include <ossimPlanet/ul.h>
+#include <fstream>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetShaderProgramSetup.h>
+
+static OpenThreads::Mutex ossimPlanet_LayerListMutex;
+static ossim_uint64 ossimPlanet_initializationCount = 0;
+static ossimTrace traceDebug("ossimPlanetApi:debug");
+
+class ossimPlanetStateBase : public ossimPlanetActionReceiver
+ {
+ public:
+ ossimPlanetStateBase(ossimPlanet_ContextType type)
+ :theContextType(type),
+ thePlanet(new ossimPlanet)
+ {
+ }
+ virtual ~ossimPlanetStateBase()
+ {
+ }
+ ossimPlanet_ContextType contextType()const
+ {
+ return theContextType;
+ }
+ const osg::ref_ptr<ossimPlanetGeoRefModel> landModel()const
+ {
+ return thePlanet->model();
+ }
+ void setPlanet(ossimPlanet* planet)
+ {
+ thePlanet = planet;
+ }
+ osg::ref_ptr<ossimPlanet> planet()
+ {
+ return thePlanet;
+ }
+ const osg::ref_ptr<ossimPlanet> planet()const
+ {
+ return thePlanet;
+ }
+ virtual void setProjectionMatrix(const osg::Matrixd& m)=0;
+ virtual void setViewport(int x, int y, int w, int h)=0;
+ virtual void setViewMatrix(const osg::Matrixd& m) = 0;
+ virtual void setViewportClearColor(const osg::Vec4& color)=0;
+ virtual bool needsRendering()
+ {
+ if(thePlanet.valid())
+ {
+ return thePlanet->redrawFlag();
+ }
+ return false;
+ }
+ virtual bool frame()=0;
+ virtual void setSceneData(){}
+ virtual void setCameraManipulator(osg::ref_ptr<osgGA::CameraManipulator> m){}
+
+ virtual void execute(const ossimPlanetAction& action)
+ {
+ ossimString command;
+ action.command(command);
+ }
+ protected:
+ ossimPlanet_ContextType theContextType;
+ osg::ref_ptr<ossimPlanet> thePlanet;
+ };
+
+#define ossimPlanetStateBaseCast(X) static_cast<ossimPlanetStateBase*>(X)
+#define ossimPlanetLayerCast(X) static_cast<ossimPlanetLayer*>(X)
+#define ossimPlanetCast(X) static_cast<ossimPlanet*>(X)
+
+class ossimPlanetStatePlanetOnly : public ossimPlanetStateBase
+{
+public:
+ ossimPlanetStatePlanetOnly()
+ :ossimPlanetStateBase(ossimPlanet_PLANET_ONLY_CONTEXT)
+ {
+ }
+ virtual void setProjectionMatrix(const osg::Matrixd& m)
+ {
+ }
+ virtual void setViewport(int x, int y, int w, int h)
+ {
+ }
+ virtual void setViewMatrix(const osg::Matrixd& m)
+ {
+ }
+ virtual void setViewportClearColor(const osg::Vec4& color)
+ {
+ }
+ virtual bool needsRendering()
+ {
+ return ossimPlanetStateBase::needsRendering();
+ }
+ virtual bool frame()
+ {
+ return false;
+ }
+};
+
+class ossimPlanetStateSceneView : public ossimPlanetStateBase
+ {
+ public:
+ ossimPlanetStateSceneView()
+ :ossimPlanetStateBase(ossimPlanet_NOVIEWER_CONTEXT),
+ theSceneView(new osgUtil::SceneView),
+ theNeedsRedrawFlag(true)
+ {
+ }
+ virtual ~ossimPlanetStateSceneView()
+ {
+ }
+ virtual void setProjectionMatrix(const osg::Matrixd& m)
+ {
+ theNeedsRedrawFlag = true;
+ theSceneView->setProjectionMatrix(m);
+ }
+ virtual void setViewport(int x, int y, int w, int h)
+ {
+ theNeedsRedrawFlag = true;
+ theSceneView->setViewport(x, y, w, h);
+ }
+ virtual void setViewMatrix(const osg::Matrixd& m)
+ {
+ theNeedsRedrawFlag = true;
+ theSceneView->setViewMatrix(m);
+ }
+ virtual void setViewportClearColor(const osg::Vec4& color)
+ {
+ theNeedsRedrawFlag = true;
+ theSceneView->setClearColor(color);
+ }
+ virtual bool needsRendering()
+ {
+ return (theNeedsRedrawFlag||ossimPlanetStateBase::needsRendering());
+ }
+ virtual void setSceneData()
+ {
+ theNeedsRedrawFlag = true;
+ theSceneView->setSceneData(thePlanet.get());
+ }
+ virtual bool frame()
+ {
+ theNeedsRedrawFlag = false;
+ theSceneView->update();
+ theSceneView->cull();
+ theSceneView->draw();
+ return true;
+ }
+ osg::ref_ptr<osgUtil::SceneView> sceneView()
+ {
+ return theSceneView.get();
+ }
+ protected:
+ osg::ref_ptr<osgUtil::SceneView> theSceneView;
+ bool theNeedsRedrawFlag;
+ };
+
+class ossimPlanetStateViewer : public ossimPlanetStateBase
+ {
+ public:
+ ossimPlanetStateViewer()
+ :ossimPlanetStateBase(ossimPlanet_VIEWER_CONTEXT),
+ theViewer(new ossimPlanetViewer)
+ {
+ theViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
+ }
+ virtual ~ossimPlanetStateViewer()
+ {
+ }
+ virtual void setProjectionMatrix(const osg::Matrixd& m)
+ {
+ theViewer->getCamera()->setProjectionMatrix(m);
+ }
+ virtual void setViewport(int x, int y, int w, int h)
+ {
+ theViewer->getCamera()->setViewport(x, y, w, h);
+ }
+ virtual void setViewMatrix(const osg::Matrixd& m)
+ {
+ theViewer->getCamera()->setViewMatrix(m);
+ }
+ virtual void setViewportClearColor(const osg::Vec4& color)
+ {
+ theViewer->getCamera()->setClearColor(color);
+ }
+ virtual bool needsRendering()
+ {
+ if(theManipulator.valid())
+ {
+ if(theManipulator->navigator()->needsContinuousUpdate())
+ {
+ return true;
+ }
+ }
+ return ossimPlanetStateBase::needsRendering();
+ }
+ virtual void setSceneData()
+ {
+ theViewer->setSceneData(thePlanet.get());
+ }
+ virtual bool frame()
+ {
+
+ if (!theViewer->isRealized())
+ {
+ theViewer->realize();
+ }
+
+ theViewer->frame();
+
+ return !theViewer->done();
+ }
+ osg::ref_ptr<osgViewer::Viewer> viewer()
+ {
+ return theViewer;
+ }
+ virtual void setCameraManipulator(osg::ref_ptr<osgGA::CameraManipulator> m)
+ {
+ theManipulator = dynamic_cast<ossimPlanetManipulator*>(m.get());
+ theViewer->setCameraManipulator(m.get());
+ }
+ protected:
+ osg::ref_ptr<ossimPlanetManipulator> theManipulator;
+ osg::ref_ptr<osgViewer::Viewer> theViewer;
+ };
+
+// private utility functions
+static void ossimPlanetPrvt_fixReceiverPath(ossimString& pathName)
+{
+ if(!pathName.empty())
+ {
+ if(pathName[(ossimString::size_type)0] != ':')
+ {
+ pathName = ":" + pathName;
+ }
+ }
+}
+static void ossimPlanetPrvt_extractSeaparatedActions(std::vector<ossimString>& result,
+ ossimPlanet_ConstStringType actions,
+ ossimPlanet_ConstStringType separator)
+
+{
+ ossimString(actions).split(result, ossimString(separator));
+}
+
+// API definitions
+//
+void ossimPlanet_addOpenSceneGraphLibraryPath(ossimPlanet_ConstStringType path,
+ ossimPlanet_BOOL insertFrontFlag)
+{
+ if(!path) return;
+ if(insertFrontFlag != ossimPlanet_TRUE)
+ {
+ osgDB::Registry::instance()->getLibraryFilePathList().push_back(path);
+ }
+ else
+ {
+ osgDB::Registry::instance()->getLibraryFilePathList().insert(osgDB::Registry::instance()->getLibraryFilePathList().begin(),
+ path);
+ }
+}
+
+void ossimPlanet_addOpenSceneGraphDataPath(ossimPlanet_ConstStringType path,
+ ossimPlanet_BOOL insertFrontFlag)
+{
+ if(!path) return;
+ if(insertFrontFlag != ossimPlanet_TRUE)
+ {
+ osgDB::Registry::instance()->getDataFilePathList().push_back(path);
+ }
+ else
+ {
+ osgDB::Registry::instance()->getDataFilePathList().insert(osgDB::Registry::instance()->getLibraryFilePathList().begin(),
+ path);
+ }
+}
+
+void ossimPlanet_loadOssimPreferenceFile(ossimPlanet_ConstStringType preferenceFile)
+{
+ ossimPreferences::instance()->loadPreferences(ossimFilename(preferenceFile));
+}
+
+void ossimPlanet_setOssimPreferenceNameValue(ossimPlanet_ConstStringType name,
+ ossimPlanet_ConstStringType value)
+{
+ ossimPreferences::instance()->addPreference(name, value);
+}
+
+void ossimPlanet_addOssimElevation(ossimPlanet_ConstStringType path)
+{
+ if(path&&ossimFilename(path).isDir())
+ {
+ ossimElevManager::instance()->loadElevationPath(path);
+ }
+}
+
+void ossimPlanet_addGeoid(ossimPlanet_ConstStringType path,
+ ossimByteOrder byteOrder,
+ ossimPlanet_BOOL insertFrontFlag)
+{
+ ossimFilename geoidFile = path;
+ if(path)
+ {
+ ossimRefPtr<ossimGeoid> geoid;
+ if(geoidFile.exists())
+ {
+ geoid = new ossimGeoidEgm96;
+ if(geoid->open(path, byteOrder))
+ {
+ ossimGeoidManager::instance()->addGeoid(geoid, insertFrontFlag==ossimPlanet_TRUE);
+ }
+ else
+ {
+ geoid = new ossimGeoidNgs;
+ if(geoid->open(path))
+ {
+ ossimGeoidManager::instance()->addGeoid(geoid, insertFrontFlag==ossimPlanet_TRUE);
+ }
+ else
+ {
+ if(traceDebug())
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "No grid handler found for path = " << ossimString(path) << "\n";
+ }
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanet_addOssimPlugin(ossimPlanet_ConstStringType path,
+ ossimPlanet_BOOL insertFrontFlag)
+{
+ ossimFilename plugin(path);
+ if(plugin.exists())
+ {
+ if(plugin.isDir())
+ {
+ ossimDirectory dir;
+ if(dir.open(plugin))
+ {
+ ossimFilename file;
+ bool loadedPluginFlag = false;
+ if(dir.getFirst(file,
+ ossimDirectory::OSSIM_DIR_FILES))
+ {
+ do
+ {
+ if(ossimSharedPluginRegistry::instance()->registerPlugin(file, insertFrontFlag==ossimPlanet_TRUE))
+ {
+ loadedPluginFlag=true;
+ }
+ }
+ while(dir.getNext(file));
+ }
+ if(!loadedPluginFlag)
+ {
+ if(traceDebug())
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "Unable find a plugin in directory " << file << "\n";
+ }
+ }
+ }
+ }
+ else
+ {
+ if(!ossimSharedPluginRegistry::instance()->registerPlugin(plugin, insertFrontFlag==ossimPlanet_TRUE))
+ {
+ if(traceDebug())
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "Unable to load plugin " << plugin << "\n";
+ }
+ }
+ }
+ }
+
+}
+
+void ossimPlanet_setTracePattern(ossimPlanet_ConstStringType pattern)
+{
+ ossimTraceManager::instance()->setTracePattern(ossimString(pattern));
+}
+
+void ossimPlanet_microSecondSleep(ossimPlanet_SizeType microSeconds)
+{
+ ulMicroSecondSleep((int)microSeconds);
+
+}
+
+void ossimPlanet_milliSecondSleep(ossimPlanet_SizeType milliSeconds)
+{
+ ulMilliSecondSleep((int)milliSeconds);
+}
+
+void ossimPlanet_secondSleep(ossimPlanet_SizeType seconds)
+{
+ ulSleep((int)seconds);
+}
+
+ossimPlanet_StatePtr ossimPlanet_newState(ossimPlanet_ContextType type)
+{
+ switch(type)
+ {
+ case ossimPlanet_PLANET_ONLY_CONTEXT:
+ {
+ return static_cast<ossimPlanet_StatePtr>(new ossimPlanetStatePlanetOnly());
+ }
+ case ossimPlanet_NOVIEWER_CONTEXT:
+ {
+ return static_cast<ossimPlanet_StatePtr>(new ossimPlanetStateSceneView());
+ }
+ case ossimPlanet_VIEWER_CONTEXT:
+ {
+ return static_cast<ossimPlanet_StatePtr>(new ossimPlanetStateViewer());
+ }
+ }
+ // should never get to here
+ return static_cast<ossimPlanet_StatePtr>(0);
+}
+
+void ossimPlanet_setStateReceiverPathName(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType path)
+{
+ if(state)
+ {
+ ossimString pathName = path;
+
+ ossimPlanetPrvt_fixReceiverPath(pathName);
+ ossimPlanetStateBaseCast(state)->setPathnameAndRegister(pathName);
+ }
+}
+
+void ossimPlanet_setPlanetReceiverPathName(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType path)
+{
+ if(state)
+ {
+ ossimString pathName = path;
+
+ ossimPlanetPrvt_fixReceiverPath(pathName);
+ ossimPlanetStateBaseCast(state)->planet()->setPathnameAndRegister(pathName);
+ }
+}
+
+void ossimPlanet_deleteState(ossimPlanet_StatePtr state)
+{
+ if(state)
+ {
+ delete ossimPlanetStateBaseCast(state);
+ }
+}
+
+void ossimPlanet_init()
+{
+ if(ossimPlanet_initializationCount == 0)
+ {
+ ossimInit::instance()->initialize();
+ }
+ ++ossimPlanet_initializationCount;
+}
+
+void ossimPlanet_initWithArgs(int* argc, char** argv[])
+{
+ if(ossimPlanet_initializationCount == 0)
+ {
+ ossimInit::instance()->initialize(*argc, *argv);
+ }
+ ++ossimPlanet_initializationCount;
+}
+
+void ossimPlanet_finalize()
+{
+ if(ossimPlanet_initializationCount > 0)
+ {
+ --ossimPlanet_initializationCount;
+ }
+
+ // do cleanup if all users have finalized
+ //
+ if(ossimPlanet_initializationCount == 0)
+ {
+ ossimInit::instance()->finalize();
+ }
+}
+
+ossimPlanet_PlanetPtr ossimPlanet_getNativePlanetPointer(ossimPlanet_StatePtr state)
+{
+ if(state)
+ {
+ return static_cast<ossimPlanet_PlanetPtr>(ossimPlanetStateBaseCast(state)->planet().get());
+ }
+ return static_cast<ossimPlanet_PlanetPtr>(0);
+}
+
+void ossimPlanet_setViewManipulator(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType typeName,
+ ossimPlanet_ConstStringType receiverPathName)
+{
+ ossimPlanetStateBase* base = ossimPlanetStateBaseCast(state);
+ if(base)
+ {
+ if(ossimString(typeName) == "ossimPlanetManipulator")
+ {
+ ossimPlanetManipulator* manipulator = new ossimPlanetManipulator();
+
+ base->setCameraManipulator( manipulator );
+ }
+ }
+}
+
+void ossimPlanet_setLandFragShaderType(ossimPlanet_StatePtr state, ossimPlanetFragShaderType type)
+{
+#if 0
+ osg::ref_ptr<ossimPlanet> ptr = ossimPlanetStateBaseCast(state)->planet();
+ if(ptr.valid())
+ {
+ if(ptr->land().valid())
+ {
+ ossimPlanetShaderProgramSetup::ossimPlanetFragmentShaderType shaderType = ossimPlanetShaderProgramSetup::NO_SHADER;
+ switch(type)
+ {
+ case ossimPlanet_NO_SHADER:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::NO_SHADER;
+ break;
+ }
+ case ossimPlanet_TOP:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::TOP;
+ break;
+ }
+ case ossimPlanet_REFERENCE:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::REFERENCE;
+ break;
+ }
+ case ossimPlanet_OPACITY:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::OPACITY;
+ break;
+ }
+ case ossimPlanet_HORIZONTAL_SWIPE:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::HORIZONTAL_SWIPE;
+ break;
+ }
+ case ossimPlanet_VERTICAL_SWIPE:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::VERTICAL_SWIPE;
+ break;
+ }
+ case ossimPlanet_BOX_SWIPE:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::BOX_SWIPE;
+ break;
+ }
+ case ossimPlanet_CIRCLE_SWIPE:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::TOP;
+ break;
+ }
+ case ossimPlanet_ABSOLUTE_DIFFERENCE:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::CIRCLE_SWIPE;
+ break;
+ }
+ case ossimPlanet_FALSE_COLOR_REPLACEMENT:
+ {
+ shaderType = ossimPlanetShaderProgramSetup::FALSE_COLOR_REPLACEMENT;
+ break;
+ }
+ }
+ ptr->land()->setCurrentFragmentShaderType(shaderType);
+ }
+ }
+#endif
+}
+
+
+void ossimPlanet_setSceneDataToView(ossimPlanet_StatePtr state)
+{
+ if(state)
+ {
+ ossimPlanetStateBaseCast(state)->setSceneData();
+ }
+}
+
+void setViewTransformationsToCurrentGlSettings(ossimPlanet_StatePtr state)
+{
+ if(state)
+ {
+ GLint viewParams[4];
+ GLdouble glMat[16];
+ osg::Matrix m;
+
+ glGetIntegerv(GL_VIEWPORT, viewParams);
+ ossimPlanetStateBaseCast(state)->setViewport(viewParams[0],
+ viewParams[1],
+ viewParams[2],
+ viewParams[3]);
+
+ glGetDoublev(GL_PROJECTION_MATRIX, glMat);
+ m.set( glMat );
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix( m );
+ // double fov, aspect, znear, zfar;
+ // globalSettings.theSceneView3d->getProjectionMatrixAsPerspective(fov, aspect, znear, zfar);
+ // std::cout << "fov = " << fov << " aspect = " << aspect << " zn = " << znear << " zf = " << zfar << std::endl;
+
+ glGetDoublev( GL_MODELVIEW_MATRIX, glMat );
+ m.set( glMat );
+ ossimPlanetStateBaseCast(state)->setViewMatrix( m );
+ }
+}
+
+void ossimPlanet_setProjectionMatrixAsPerspective(ossimPlanet_StatePtr state,
+ double fovValue,
+ double aspectRatioValue,
+ double nearValue,
+ double farValue)
+{
+ if(state)
+ {
+ osg::Matrixd m;
+ m.makePerspective(fovValue, aspectRatioValue, nearValue, farValue);
+ //m.makePerspective(fov, aspectRatio, near, far);
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix(m);
+ }
+}
+
+void ossimPlanet_setProjectionMatrixAsFrustum(ossimPlanet_StatePtr state,
+ double left, double right,
+ double bottom, double top,
+ double zNear, double zFar)
+{
+ if(state)
+ {
+ osg::Matrixd m;
+ m.makeFrustum(left, right, bottom, top, zNear, zFar);
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix(m);
+ }
+}
+
+void ossimPlanet_setProjectionMatrixAsOrtho(ossimPlanet_StatePtr state,
+ double left, double right,
+ double bottom, double top,
+ double zNear, double zFar)
+{
+ if(state)
+ {
+ osg::Matrixd m;
+ m.makeOrtho(left, right, bottom, top, zNear, zFar);
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix(m);
+ }
+}
+
+void ossimPlanet_setProjectionMatrixAsOrtho2D(ossimPlanet_StatePtr state,
+ double left, double right,
+ double bottom, double top)
+{
+ if(state)
+ {
+ osg::Matrixd m;
+ m.makeOrtho2D(left, right, bottom, top);
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix(m);
+ }
+}
+
+void ossimPlanet_setProjectionMatrixAsRowOrderedArray(ossimPlanet_StatePtr state,
+ double* m)
+{
+ if(state&&m)
+ {
+ osg::Matrixd mResult;
+ mResult.set(m);
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix(mResult);
+ }
+}
+
+void ossimPlanet_setProjectionMatrix(ossimPlanet_StatePtr state,
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33)
+{
+ if(state)
+ {
+ ossimPlanetStateBaseCast(state)->setProjectionMatrix(osg::Matrixd(m00, m01, m02, m03,
+ m10, m11, m12, m13,
+ m20, m21, m22, m23,
+ m30, m31, m32, m33));
+ }
+}
+void ossimPlanet_setViewMatrixAsLlhHprRelativeTangent(ossimPlanet_StatePtr state,
+ double lat,
+ double lon,
+ double height,
+ double heading,
+ double pitch,
+ double roll)
+{
+ if(state)
+ {
+ const osg::ref_ptr<ossimPlanetGeoRefModel> model = ossimPlanetStateBaseCast(state)->landModel();
+ if(!model.valid()) return;
+ osg::Matrixd output;
+ osg::Vec3d xyz;
+ model->forward(osg::Vec3d(lat, lon, height),
+ xyz);
+
+ model->lsrMatrix(osg::Vec3d(lat, lon, height),
+ output,
+ heading);
+ output(3,0) = 0.0;
+ output(3,1) = 0.0;
+ output(3,2) = 0.0;
+
+
+ NEWMAT::Matrix orien = (ossimMatrix4x4::createRotationXMatrix(pitch, OSSIM_LEFT_HANDED)*
+ ossimMatrix4x4::createRotationYMatrix(roll, OSSIM_LEFT_HANDED));
+ // now transpose since ossim matrix is column oriented and OSG is row oriented
+ osg::Matrixd tempM(orien[0][0], orien[1][0], orien[2][0], 0.0,
+ orien[0][1], orien[1][1], orien[2][1], 0.0,
+ orien[0][2], orien[1][2], orien[2][2], 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+
+ ossimPlanetStateBaseCast(state)->setViewMatrix(osg::Matrix::inverse(tempM*output*osg::Matrixd::translate(xyz[0], xyz[1], xyz[2])));
+ }
+}
+
+void ossimPlanet_setViewMatrixAsRowOrderedArray(ossimPlanet_StatePtr state,
+ const double *m)
+{
+ if(state)
+ {
+ osg::Matrixd mResult;
+ mResult.set(m);
+ ossimPlanetStateBaseCast(state)->setViewMatrix(mResult);
+ }
+}
+
+void ossimPlanet_setViewMatrix(ossimPlanet_StatePtr state,
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33)
+{
+ if(state)
+ {
+ ossimPlanetStateBaseCast(state)->setViewMatrix(osg::Matrixd(m00, m01, m02, m03,
+ m10, m11, m12, m13,
+ m20, m21, m22, m23,
+ m30, m31, m32, m33));
+ }
+}
+
+void ossimPlanet_setViewport(ossimPlanet_StatePtr state,
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ if(state)
+ {
+ ossimPlanetStateBaseCast(state)->setViewport(x, y, w, h);
+ }
+}
+
+void ossimPlanet_setViewportClearColor(ossimPlanet_StatePtr state,
+ float red,
+ float green,
+ float blue,
+ float alpha)
+{
+ if(state)
+ {
+ ossimPlanetStateBaseCast(state)->setViewportClearColor(osg::Vec4(red, green, blue, alpha));
+ }
+}
+
+ossimPlanet_BOOL ossimPlanet_renderFrame(ossimPlanet_StatePtr state)
+{
+ if(state)
+ {
+ ossimPlanetStateBaseCast(state)->planet()->resetAllRedrawFlags();
+ return ossimPlanetStateBaseCast(state)->frame()?ossimPlanet_TRUE:ossimPlanet_FALSE;
+ }
+ return ossimPlanet_FALSE;
+}
+
+ossimPlanet_BOOL ossimPlanet_renderFramePreserveState(ossimPlanet_StatePtr state)
+{
+ ossimPlanet_BOOL result = ossimPlanet_TRUE;
+
+ ossimPlanet_pushState();
+ result = ossimPlanet_renderFrame(state);
+ ossimPlanet_popState();
+
+ return result;
+}
+
+ossimPlanet_BOOL ossimPlanet_needsRendering(ossimPlanet_StatePtr state)
+{
+ if(state)
+ {
+ return ossimPlanetStateBaseCast(state)->needsRendering()?ossimPlanet_TRUE:ossimPlanet_FALSE;
+ }
+
+ return ossimPlanet_FALSE;
+}
+
+void ossimPlanet_pushState()
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+}
+
+void ossimPlanet_popState()
+{
+ glMatrixMode(GL_TEXTURE);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glPopAttrib();
+}
+
+ossimPlanet_LayerPtr ossimPlanet_addLayer(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType layerType,
+ ossimPlanet_ConstStringType name,
+ ossimPlanet_ConstStringType id,
+ ossimPlanet_ConstStringType description,
+ ossimPlanet_ConstStringType receiverPathName)
+{
+ ossimPlanet_LayerPtr result = 0;
+ if(state)
+ {
+ osg::ref_ptr<ossimPlanetLayer> layer = ossimPlanetLayerRegistry::instance()->create(ossimString(layerType));
+ if(layer.valid())
+ {
+ ossimPlanet_setLayerName(static_cast<ossimPlanet_LayerPtr>(layer.get()), name);
+ ossimPlanet_setLayerId(static_cast<ossimPlanet_LayerPtr>(layer.get()), id);
+ ossimPlanet_setLayerDescription(static_cast<ossimPlanet_LayerPtr>(layer.get()), description);
+ ossimPlanet_setLayerReceiverPathName(static_cast<ossimPlanet_LayerPtr>(layer.get()), receiverPathName);
+ result = static_cast<ossimPlanet_LayerPtr>(layer.get());
+ ossimPlanet_LayerListMutex.lock();
+ ossimPlanetStateBaseCast(state)->planet()->addChild(layer.get());
+ ossimPlanet_LayerListMutex.unlock();
+ }
+ }
+
+ return result;
+}
+
+OSSIMPLANET_DLL void ossimPlanet_removeLayerGivenPtr(ossimPlanet_StatePtr state,
+ ossimPlanet_LayerPtr layerPtr)
+{
+ ossimPlanet_IndexType idx = ossimPlanet_getIndexOfLayerGivenPtr(state, layerPtr);
+ if(idx != ossimPlanet_INVALID_INDEX)
+ {
+ ossimPlanet_LayerListMutex.lock();
+ ossimPlanetStateBaseCast(state)->planet()->removeChildren(idx, 1);
+ ossimPlanet_LayerListMutex.unlock();
+ }
+}
+
+ossimPlanet_SizeType ossimPlanet_getNumberOfLayers(ossimPlanet_StatePtr state)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(state)
+ {
+ return static_cast<ossimPlanet_SizeType>(ossimPlanetStateBaseCast(state)->planet()->getNumChildren());
+ }
+
+ return 0;
+}
+
+ossimPlanet_IndexType ossimPlanet_getIndexOfLayerGivenPtr(ossimPlanet_StatePtr state,
+ ossimPlanet_LayerPtr layerPtr)
+{
+ ossimPlanet_IndexType result = ossimPlanet_INVALID_INDEX;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+
+ if(state&&layerPtr)
+ {
+ ossimPlanet* planet = ossimPlanetStateBaseCast(state)->planet().get();
+ ossimPlanetLayer* layerTest = ossimPlanetLayerCast(layerPtr);
+ if(!planet) return result;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upperIndex = planet->getNumChildren();
+ for(; ((idx < upperIndex)&&(result == ossimPlanet_INVALID_INDEX));++idx)
+ {
+ ossimPlanetLayer* l = dynamic_cast<ossimPlanetLayer*>(planet->getChild(idx));
+ if(l == layerTest)
+ {
+ result = idx;
+ }
+ }
+ }
+
+ return result;
+}
+
+ossimPlanet_LayerPtr ossimPlanet_getLayerGivenIndex(ossimPlanet_StatePtr state,
+ ossimPlanet_IndexType idx)
+{
+ ossimPlanet_LayerPtr result = 0;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+
+ if(state&&(idx>=0))
+ {
+ ossimPlanet* planet = ossimPlanetStateBaseCast(state)->planet().get();
+ if(!planet) return result;
+ if(idx < static_cast<ossimPlanet_IndexType>(planet->getNumChildren()))
+ {
+ result = dynamic_cast<ossimPlanetLayer*>(planet->getChild(idx));
+ }
+ }
+
+ return result;
+}
+
+ossimPlanet_LayerPtr ossimPlanet_getLayerGivenId(ossimPlanet_StatePtr state,
+ ossimPlanet_ConstStringType id)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ ossimPlanet_LayerPtr result = 0;
+ ossimString idString(id);
+
+ if(state&&!idString.empty())
+ {
+ ossimPlanet* planet = ossimPlanetStateBaseCast(state)->planet().get();
+ if(!planet) return result;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upperIndex = planet->getNumChildren();
+ for(; ((idx < upperIndex)&&(result==0));++idx)
+ {
+ ossimPlanetLayer* l = dynamic_cast<ossimPlanetLayer*>(planet->getChild(idx));
+ if(l&&l->id()==idString)
+ {
+ result = l;
+ }
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanet_setLayerId(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType id)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(layer)
+ {
+ ossimPlanetLayerCast(layer)->setId(ossimString(id));
+ }
+}
+
+void ossimPlanet_setLayerName(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType name)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(layer)
+ {
+ ossimPlanetLayerCast(layer)->setName(ossimString(name));
+ }
+}
+
+void ossimPlanet_setLayerDescription(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType description)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(layer)
+ {
+ ossimPlanetLayerCast(layer)->setDescription(ossimString(description));
+ }
+}
+
+
+void ossimPlanet_setLayerReceiverPathName(ossimPlanet_LayerPtr layer,
+ ossimPlanet_ConstStringType receiverPathName)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(layer)
+ {
+ ossimString pathName = receiverPathName;
+ ossimPlanetPrvt_fixReceiverPath(pathName);
+ if(!pathName.empty())
+ {
+ ossimPlanetLayerCast(layer)->setPathnameAndRegister(pathName);
+ }
+ }
+}
+
+ossimPlanet_BOOL ossimPlanet_getLayerEnableFlag(ossimPlanet_LayerPtr layer)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(layer)
+ {
+ bool flag = ossimPlanetLayerCast(layer)->enableFlag();
+
+ return flag?ossimPlanet_TRUE:ossimPlanet_FALSE;
+ }
+ return ossimPlanet_FALSE;
+}
+
+void ossimPlanet_setLayerEnableFlag(ossimPlanet_LayerPtr layer,
+ ossimPlanet_BOOL flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(ossimPlanet_LayerListMutex);
+ if(layer)
+ {
+ ossimPlanetLayerCast(layer)->setEnableFlag(flag==ossimPlanet_TRUE);
+ }
+}
+
+void ossimPlanet_addImageToReceiver(ossimPlanet_ConstStringType location,
+ ossimPlanet_ConstStringType receiverName,
+ ossimPlanet_BOOL addInTheBackgroundFlag)
+{
+ ossimFilename loc(location);
+ if(!loc.exists()) return;
+
+ if(loc.isDir())
+ {
+ ossimFilename file;
+ ossimDirectory dir(location);
+ if(dir.getFirst(file, ossimDirectory::OSSIM_DIR_FILES))
+ {
+ do
+ {
+ if((file.ext() != "his")&&
+ (file.ext() != "ovr"))
+ {
+ ossimString action;
+
+ action += "<Add target=\""+ossimString(receiverName)+"\">";
+ action += "<Image>";
+ action += ossimString("<id>")+ossimString(file)+ossimString("</id>");
+ action += ossimString("<name>")+ossimString(file)+ossimString("</name>");
+ action += ossimString("<filename>")+ossimString(file)+ossimString("</filename>");
+ action += "</Image>";
+ action += "</Add>";
+ if(addInTheBackgroundFlag == ossimPlanet_TRUE)
+ {
+ ossimPlanet_postXmlAction(action.c_str());
+ }
+ else
+ {
+ ossimPlanet_executeXmlAction(action.c_str());
+ }
+ }
+ }while(dir.getNext(file));
+ }
+ }
+ else
+ {
+ ossimString action;
+
+ action += "<Add target=\""+ossimString(receiverName)+"\">";
+ action += "<Image>";
+ action += ossimString("<id>")+ossimString(location)+ossimString("</id>");
+ action += ossimString("<name>")+ossimString(location)+ossimString("</name>");
+ action += ossimString("<filename>")+ossimString(location)+ossimString("</filename>");
+ action += "</Image>";
+ action += "</Add>";
+
+ if(addInTheBackgroundFlag == ossimPlanet_TRUE)
+ {
+ ossimPlanet_postXmlAction(action.c_str());
+ }
+ else
+ {
+ ossimPlanet_executeXmlAction(action.c_str());
+ }
+ }
+}
+
+OSSIMPLANET_DLL void ossimPlanet_addTextureLayersFromKwlFile(ossimPlanet_StatePtr state,
+ const char* kwlFile)
+{
+#if 0
+ ossimKeywordlist kwl;
+ kwl.addFile(kwlFile);
+
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(kwl.toString());
+ if(layer.valid())
+ {
+ ossimPlanetStateBaseCast(state)->planet()->land()->referenceLayer()->addTop(layer.get());
+ }
+#endif
+}
+
+
+void ossimPlanet_executeXmlAction(ossimPlanet_ConstStringType completeAction)
+{
+ ossimPlanetXmlAction(completeAction).execute();
+}
+
+void ossimPlanet_postXmlAction(ossimPlanet_ConstStringType completeAction)
+{
+ ossimPlanetXmlAction(completeAction).post();
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetArchive.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetArchive.cpp
new file mode 100755
index 0000000..af613d4
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetArchive.cpp
@@ -0,0 +1,199 @@
+
+#include <ossim/base/ossimNotify.h>
+#include <ossimPlanet/ossimPlanetArchive.h>
+
+
+
+ossimPlanetArchive::ossimPlanetArchive()
+{
+ useArchiveMapping = false;
+}
+
+ossimPlanetArchive::~ossimPlanetArchive()
+{
+}
+
+void ossimPlanetArchive::addMapping(ossimPlanetArchiveMapping &mapping)
+{
+ OpenThreads::ScopedLock<ossimPlanetReentrantMutex> lock(theArchiveMutex);
+
+ // test to see if the mapping has an ending slash... if not add one
+ ossimFilename src = mapping.getSource();
+ ossimFilename dest = mapping.getDestination();
+
+ src = convertToDirectory(src);
+ dest = convertToDirectory(dest);
+
+ mapping.setSource(src);
+ mapping.setDestination(dest);
+
+ mappingList.push_back(mapping);
+}
+
+
+ossimFilename ossimPlanetArchive::convertToDirectory(ossimFilename &filename)
+{
+ ossimString drive;
+ ossimString path;
+ ossimString file;
+ ossimString ext;
+
+ filename.split(drive, path, file, ext);
+
+ // if the drive is empty its a unix/linux drive
+ if( drive.empty() )
+ {
+ return (filename[filename.length()-1] != '/')? ossimFilename(filename.append("/")) : filename;
+ }
+ // else its a windows drive
+ else
+ {
+ return (filename[filename.length()-1] != '\\')? ossimFilename(filename.append("\\")) : filename;
+ }
+}
+
+
+void ossimPlanetArchive::removeMapping(ossimPlanetArchiveMapping &mapping)
+{
+ OpenThreads::ScopedLock<ossimPlanetReentrantMutex> lock(theArchiveMutex);
+ ossim_uint32 row = 0;
+ for( row = 0; row < mappingList.size(); row++ )
+ {
+ if( (mapping.getSource() == mappingList[row].getSource()) &&
+ (mapping.getDestination() == mappingList[row].getDestination()) )
+ {
+ break;
+ }
+ }
+
+ if( row < mappingList.size() )
+ {
+ mappingList.erase(mappingList.begin() + row);
+ }
+}
+
+ossimFilename ossimPlanetArchive::matchPath(const ossimFilename &filename)
+{
+ OpenThreads::ScopedLock<ossimPlanetReentrantMutex> lock(theArchiveMutex);
+ std::vector<ossimPlanetArchiveMapping>::iterator it;
+
+ if( mappingList.empty() || filename.exists() )
+ return filename;
+
+ ossimString file_drive;
+ ossimString file_path;
+ ossimString file_file;
+ ossimString file_ext;
+
+ ossimString src_drive;
+ ossimString src_path;
+ ossimString src_file;
+ ossimString src_ext;
+
+ ossimString dest_drive;
+ ossimString dest_path;
+ ossimString dest_file;
+ ossimString dest_ext;
+
+ ossimFilename src;
+ ossimFilename dest;
+
+ filename.split(file_drive, file_path, file_file, file_ext);
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - filename split: drive=" << file_drive << " path=" << file_path << " file=" << file_file << " ext=" << file_ext << std::endl;
+ ossimPlanetArchiveMapping opam;
+
+ // try to clean this up
+ // first test for the exact match (drive and path)
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - finding exact file_path" << std::endl;
+
+ // test for a path only match
+ for( it = mappingList.begin(); it != mappingList.end(); it++ )
+ {
+ opam = (*it);
+
+ src = opam.getSource();
+ src.split(src_drive, src_path, src_file, src_ext);
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - src split: drive=" << src_drive << " path=" << src_path << " file=" << src_file << " ext=" << src_ext << std::endl;
+
+ if( (file_path == src_path) )
+ {
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - match found. File: " << file_path << " Source: " << src_path << std::endl;
+ dest = opam.getDestination();
+ dest.split(dest_drive, dest_path, dest_file, dest_ext);
+ dest.merge(dest_drive, dest_path, file_file, file_ext);
+ //dest.convertForwardToBackSlashes();
+ return dest;
+ }
+ }
+
+
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - finding exact file_drive/file_path" << std::endl;
+ for( it = mappingList.begin(); it != mappingList.end(); it++ )
+ {
+ opam = (*it);
+
+ src = opam.getSource();
+ src.split(src_drive, src_path, src_file, src_ext);
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - src split: drive=" << src_drive << " path=" << src_path << " file=" << src_file << " ext=" << src_ext << std::endl;
+
+ if( (file_drive+file_path) == (src_drive+src_path) )
+ {
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - match found. File: " << file_drive << " " << file_path << " Source: " << src_drive << " " << src_path << std::endl;
+ dest = opam.getDestination();
+ dest.split(dest_drive, dest_path, dest_file, dest_ext);
+ dest.merge(dest_drive, dest_path, file_file, file_ext);
+ //dest.convertForwardToBackSlashes();
+ return dest;
+ }
+ }
+
+
+ // any sub path of the given filename
+ // Fail safe: this is a complete hack... need to find a better way to do this
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - if path contains src_path" << std::endl;
+ for( it = mappingList.begin(); it != mappingList.end(); it++ )
+ {
+ opam = (*it);
+
+ src = opam.getSource();
+ src.split(src_drive, src_path, src_file, src_ext);
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - src split: drive=" << src_drive << " path=" << src_path << " file=" << src_file << " ext=" << src_ext << std::endl;
+
+ if( file_path.contains( src_path ) )
+ {
+ ossimNotify(ossimNotifyLevel_INFO) << "ossimPlanetArchive::matchPath() - match found. File: " << src_path << " Source: " << std::endl;
+ dest = opam.getDestination();
+ dest.split(dest_drive, dest_path, dest_file, dest_ext);
+ dest.merge(dest_drive, file_path, file_file, file_ext);
+ //dest.convertForwardToBackSlashes();
+
+ return dest;
+ }
+ }
+
+ // if all else fails...
+ //dest = opam.getDestination();
+ //dest.split(dest_drive, dest_path, dest_file, dest_ext);
+ //dest.merge(ossimString("x:"), file_path, file_file, file_ext);
+ //dest.convertForwardToBackSlashes();
+
+ //return dest;
+
+ return filename;
+}
+
+void ossimPlanetArchive::setArchiveMappingEnabledFlag(bool enabled)
+{
+ OpenThreads::ScopedLock<ossimPlanetReentrantMutex> lock(theArchiveMutex);
+ useArchiveMapping = enabled;
+}
+
+bool ossimPlanetArchive::archiveMappingEnabled()
+{
+ return useArchiveMapping;
+}
+
+std::vector<ossimPlanetArchiveMapping> ossimPlanetArchive::getMappingList()
+{
+ return mappingList;
+}
\ No newline at end of file
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetArchiveMapping.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetArchiveMapping.cpp
new file mode 100755
index 0000000..a478bcc
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetArchiveMapping.cpp
@@ -0,0 +1,36 @@
+#include <ossimPlanet/ossimPlanetArchiveMapping.h>
+
+
+ossimPlanetArchiveMapping::ossimPlanetArchiveMapping()
+{
+}
+
+ossimPlanetArchiveMapping::ossimPlanetArchiveMapping(const ossimFilename &source, const ossimFilename &destination)
+{
+ src = source;
+ dest = destination;
+}
+
+ossimPlanetArchiveMapping::~ossimPlanetArchiveMapping()
+{
+}
+
+ossimFilename ossimPlanetArchiveMapping::getSource()
+{
+ return src;
+}
+
+void ossimPlanetArchiveMapping::setSource(const ossimFilename &source)
+{
+ src = source;
+}
+
+ossimFilename ossimPlanetArchiveMapping::getDestination()
+{
+ return dest;
+}
+
+void ossimPlanetArchiveMapping::setDestination(const ossimFilename &destination)
+{
+ dest = destination;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetBillboardIcon.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetBillboardIcon.cpp
new file mode 100644
index 0000000..90846f2
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetBillboardIcon.cpp
@@ -0,0 +1,129 @@
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetBillboardIcon.h>
+#include <osgUtil/CullVisitor>
+#include <iostream>
+
+ossimPlanetBillboardIcon::ossimPlanetBillboardIcon(double objectGroundSize)
+{
+ thePixelWidth = 32;
+ thePixelHeight = 32;
+ theMaxPixelSize = 32; // will be reset to the images max width height
+ theMinPixelSize = 4;
+ theNeedsUpdateFlag = true;
+ theBillboard = new osg::Billboard;
+ theBillboard->setMode(osg::Billboard::POINT_ROT_EYE);
+ theGeom = new ossimPlanetIconGeom();
+ theBillboard->addDrawable(theGeom.get());
+ theBillboardTransform = new osg::MatrixTransform;
+ theBillboardTransform->addChild(theBillboard);
+ theFudgeFactorTransform = new osg::MatrixTransform;
+ theFudgeFactorTransform->addChild(theBillboardTransform.get());
+ setUpdateCallback(new ossimPlanetBillboardIconUpdateCallback);
+ // we will set the scale for now so the icon comes in
+ // at full res at approximately 5 kilomeer coverage.
+ theBillboardTransform->setMatrix(osg::Matrixd::scale(objectGroundSize, objectGroundSize, objectGroundSize));
+}
+
+void ossimPlanetBillboardIcon::setGroundObjectSize(double groundSize)
+{
+ theBillboardTransform->setMatrix(osg::Matrixd::scale(groundSize,
+ groundSize,
+ groundSize));
+}
+
+void ossimPlanetBillboardIcon::setIcon(osg::ref_ptr<osg::Image> img)
+{
+ thePixelWidth = img->s();
+ thePixelHeight = img->t();
+ theMaxPixelSize = ossim::max(thePixelWidth, thePixelHeight);
+ theGeom->setTexture(img.get());
+ dirtyBound();
+}
+
+void ossimPlanetBillboardIcon::setIcon(osg::ref_ptr<osg::Texture2D> img)
+{
+ theGeom->setTexture(img.get());
+
+ dirtyBound();
+}
+
+void ossimPlanetBillboardIcon::setGeom(osg::ref_ptr<ossimPlanetIconGeom> geom)
+{
+ theBillboard->setDrawable(0, geom.get());
+ theGeom = geom.get();
+ if(geom->texture().valid())
+ {
+ osg::Image* img = geom->texture()->getImage();
+ if(img)
+ {
+ thePixelWidth = img->s();
+ thePixelHeight = img->t();
+ theMaxPixelSize = ossim::max(thePixelWidth, thePixelHeight);
+ }
+ }
+ dirtyBound();
+}
+
+void ossimPlanetBillboardIcon::traverse(osg::NodeVisitor& nv)
+{
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(theNeedsUpdateFlag)
+ {
+ theFudgeFactorTransform->setMatrix(theFudgeFactorMatrix);
+ theNeedsUpdateFlag = false;
+ dirtyBound();
+ }
+ theFudgeFactorTransform->accept(nv);
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osgUtil::CullVisitor* cullVisitor = (osgUtil::CullVisitor*)(&nv);
+ // make sure we compute scales from the original bill board geom and not from the current
+ // bounds of the theTransform node.
+ //
+ const osg::BoundingSphere& bs = theBillboardTransform->getBound();
+ double pixelSize = ossim::abs(cullVisitor->pixelSize(bs));
+ double scaleFactor = theMaxPixelSize/pixelSize;
+ //do some sanity checks
+ if(pixelSize < theMinPixelSize)
+ {
+ scaleFactor = theMinPixelSize/pixelSize;
+ }
+ else if(pixelSize < theMaxPixelSize)
+ {
+ scaleFactor = 1.0;
+ }
+ theTranslate =osg::Vec3d(0.0,0.0,bs.radius()*.5*scaleFactor);
+ theFudgeFactorMatrix = (osg::Matrixd::scale(osg::Vec3d(scaleFactor,
+ scaleFactor,
+ scaleFactor))*
+ osg::Matrixd::translate(theTranslate));
+ theNeedsUpdateFlag = true;
+ theCulledFlag = cullVisitor->isCulled(*theFudgeFactorTransform);
+ if(!theCulledFlag)
+ {
+ theFudgeFactorTransform->accept(nv);
+ }
+ break;
+ }
+ default:
+ {
+ theFudgeFactorTransform->accept(nv);
+ break;
+ }
+ }
+}
+
+osg::BoundingSphere ossimPlanetBillboardIcon::computeBound() const
+{
+ return theFudgeFactorTransform->getBound();
+}
+
+bool ossimPlanetBillboardIcon::isCulled()const
+{
+ return theCulledFlag;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetBoundingBox.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetBoundingBox.cpp
new file mode 100644
index 0000000..ee4127d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetBoundingBox.cpp
@@ -0,0 +1,56 @@
+#include <ossimPlanet/ossimPlanetBoundingBox.h>
+
+#include <osg/Vec4>
+#include <iostream>
+
+bool ossimPlanetBoundingBox::intersects(const osg::Polytope& frustum)const
+{
+ const osg::Polytope::PlaneList& planeList = frustum.getPlaneList();
+ unsigned int idx = 0;
+ unsigned int ptIdx = 0;
+ unsigned int outsideCount = 0;
+ unsigned int upperBound = planeList.size();
+ double testValue = 0.0;
+ for(; idx < upperBound;++idx)
+ {
+ const osg::Vec4& plane = planeList[idx].asVec4();
+ outsideCount = 0;
+ for(ptIdx = 0; ptIdx < 8; ++ptIdx)
+ {
+ testValue = (((((double)plane[0])*theCorners[ptIdx][0] +
+ ((double)plane[1])*theCorners[ptIdx][1] +
+ ((double)plane[2])*theCorners[ptIdx][2])) + (double)plane[3]);
+ if(testValue >-FLT_EPSILON)
+ {
+ break;
+ }
+ else
+ {
+ ++outsideCount;
+ }
+ }
+ if(outsideCount == 8)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ossimPlanetBoundingBox::isInFront(const osg::Vec3d& eye,
+ const osg::Vec3d& direction)const
+{
+ ossim_uint32 idx = 0;
+ osg::Vec3d deltaP;
+ for(idx = 0; idx < 8; ++idx)
+ {
+ deltaP = theCorners[idx]-eye;
+ if((deltaP*direction) > -FLT_EPSILON)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetCache.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetCache.cpp
new file mode 100644
index 0000000..d0b56f9
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetCache.cpp
@@ -0,0 +1,195 @@
+#include <ossimPlanet/ossimPlanetCache.h>
+#include <ossimPlanet/ossimPlanetJpegImage.h>
+#include <ossim/imaging/ossimJpegWriter.h>
+#include <ossim/imaging/ossimMemoryImageSource.h>
+#include <ossim/imaging/ossimJpegTileSource.h>
+void ossimPlanetMemoryImageCache::shrink()
+{
+ if(!exceedsMinCacheSize())
+ {
+ return;
+ }
+ osg::Timer* timer = osg::Timer::instance();
+ ossim_float64 t;
+ while(exceedsMinCacheSize())
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ t = timer->tick();
+ TileMap::iterator iter = theTileCache.begin();
+ TileMap::iterator currentToErase = iter;
+ ossim_float64 delta = timer->delta_m(iter->second.theTimeStamp,
+ t);
+ ossim_float64 testDelta = delta;
+ ++iter;
+ while(iter!=theTileCache.end())
+ {
+ testDelta = timer->delta_m(iter->second.theTimeStamp,
+ t);
+ if(testDelta > delta)
+ {
+ currentToErase = iter;
+ delta = testDelta;
+ }
+ ++iter;
+ }
+ if(currentToErase != theTileCache.end())
+ {
+ theCurrentCacheSize -= currentToErase->second.theImage->sizeInBytes();
+ if(theCurrentCacheSize < 0) theCurrentCacheSize = 0;
+ theTileCache.erase(currentToErase);
+ }
+ }
+ }
+}
+
+void ossimPlanetMemoryImageCache::addOrUpdate(ossimPlanetImage* image)
+{
+ if(!image||(maxCacheSizeInBytes()<=0)||!enabledFlag())
+ {
+ return;
+ }
+ ossimPlanetTerrainTileId tileId = image->tileId();
+ if(!get(tileId))
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ TileInfo info;
+ info.theImage = image;
+ info.theTimeStamp = osg::Timer::instance()->tick();
+ theTileCache.insert(std::make_pair(tileId, info));
+ theCurrentCacheSize += image->sizeInBytes();
+ }
+ }
+}
+
+ossimPlanetImage* ossimPlanetMemoryImageCache::get(const ossimPlanetTerrainTileId& id)
+{
+ if(!enabledFlag()) return 0;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ TileMap::iterator tile = theTileCache.find(id);
+ if(tile!=theTileCache.end())
+ {
+ tile->second.theTimeStamp = osg::Timer::instance()->tick();
+ return tile->second.theImage.get();
+ }
+
+ return 0;
+}
+
+bool ossimPlanetMemoryImageCache::hasImage(const ossimPlanetTerrainTileId& id)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return (theTileCache.find(id) != theTileCache.end());
+}
+
+ossimPlanetDiskImageCache::ossimPlanetDiskImageCache()
+{
+
+}
+
+bool ossimPlanetDiskImageCache::openDirectory(const ossimFilename& file, bool createIfNotExistsFlag)
+{
+ bool result = false;
+ m_indexFileKwl.clear();
+ if(createIfNotExistsFlag&&!file.exists())
+ {
+ file.createDirectory(true);
+ }
+ if(file.exists())
+ {
+ m_directory = file;
+ m_indexFile = file.dirCat("cache.idx");
+ if(m_indexFile.exists())
+ {
+ m_indexFileKwl.addFile(m_indexFile.c_str());
+ }
+
+ result = true;
+ }
+
+ return result;
+}
+
+void ossimPlanetDiskImageCache::clean()
+{
+}
+
+void ossimPlanetDiskImageCache::shrink()
+{
+}
+
+void ossimPlanetDiskImageCache::addOrUpdate(ossimPlanetImage* image)
+{
+ ossimFilename tileFile = m_directory.dirCat(buildTileFile(image->tileId()));
+
+ ossimFilename directory = tileFile.path();
+ if(!directory.exists())
+ {
+ directory.createDirectory(true);
+ }
+
+ if(directory.exists())
+ {
+ ossimRefPtr<ossimJpegWriter> jpegWriter = new ossimJpegWriter;
+ ossimRefPtr<ossimMemoryImageSource> memSource = new ossimMemoryImageSource;
+ ossimRefPtr<ossimImageData> data = new ossimImageData(0, OSSIM_UINT8, image->getNumberOfComponents(), image->getWidth(), image->getHeight());
+ data->loadTile(image->data(), data->getImageRectangle(),OSSIM_BIP);
+
+ memSource->setImage(data.get());
+ jpegWriter->connectMyInputTo(memSource.get());
+ jpegWriter->setFilename(tileFile);
+ jpegWriter->execute();
+ jpegWriter->disconnect();
+ memSource->disconnect();
+ }
+}
+
+bool ossimPlanetDiskImageCache::hasImage(const ossimPlanetTerrainTileId& id)const
+{
+ ossimFilename tileFile = m_directory.dirCat(buildTileFile(id));
+
+ return tileFile.exists();
+}
+
+ossimPlanetImage* ossimPlanetDiskImageCache::get(const ossimPlanetTerrainTileId& id)
+{
+ ossimFilename tileFile = m_directory.dirCat(buildTileFile(id));
+ osg::ref_ptr<ossimPlanetImage> result;
+
+ if(tileFile.exists())
+ {
+ ossimRefPtr<ossimJpegTileSource> jpegReader = new ossimJpegTileSource;
+ if(jpegReader->open(tileFile))
+ {
+ ossimRefPtr<ossimImageData> data = jpegReader->getTile(jpegReader->getBoundingRect());
+
+ if(data.valid())
+ {
+ result = new ossimPlanetImage(id);
+ result->fromOssimImage(data.get());
+ }
+ }
+// ossimPlanetJpegImage jpegImageTile;
+
+// result = new ossimPlanetImage(id);
+
+// if(!jpegImageTile.loadFile(tileFile, *result))
+// {
+// result = 0;
+// }
+ }
+
+ return result.release();
+}
+
+ossimFilename ossimPlanetDiskImageCache::buildTileFile(const ossimPlanetTerrainTileId& id)const
+{
+ ossimFilename tileFile = ossimString::toString(id.face());
+ tileFile = tileFile.dirCat(ossimString::toString(id.level()));
+ tileFile = tileFile.dirCat(ossimString::toString(id.x()));
+ tileFile = tileFile.dirCat(ossimString::toString(id.y()));
+
+ return tileFile;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetCacheTextureLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetCacheTextureLayer.cpp
new file mode 100644
index 0000000..e406ac2
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetCacheTextureLayer.cpp
@@ -0,0 +1,283 @@
+#include <ossimPlanet/ossimPlanetCacheTextureLayer.h>
+
+ossimPlanetCacheTextureLayer::ossimPlanetCacheTextureLayer()
+{
+
+}
+
+ossimPlanetCacheTextureLayer::ossimPlanetCacheTextureLayer(const ossimPlanetCacheTextureLayer& src)
+:m_textureLayer(src.m_textureLayer.get()),
+m_cache(src.m_cache.get())
+{
+
+}
+
+ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::dup()const
+{
+ return new ossimPlanetCacheTextureLayer(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::dupType()const
+{
+ return new ossimPlanetCacheTextureLayer();
+}
+
+ossimString ossimPlanetCacheTextureLayer::getClassName()const
+{
+ return "ossimPlanetCacheTextureLayer";
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetCacheTextureLayer::updateExtents()
+{
+ ossimPlanetTextureLayerStateCode result = ossimPlanetTextureLayer_NO_SOURCE_DATA;
+ if(m_textureLayer.valid())
+ {
+ result = m_textureLayer->updateExtents();
+ theExtents = m_textureLayer->getExtents();
+ }
+
+ return result;
+}
+
+void ossimPlanetCacheTextureLayer::updateStats()const
+{
+
+}
+
+void ossimPlanetCacheTextureLayer::setTextureLayer(ossimPlanetTextureLayer* layer)
+{
+ m_textureLayer = layer;
+}
+
+void ossimPlanetCacheTextureLayer::setCache(ossimPlanetImageCache* cache)
+{
+ m_cache = cache;
+}
+
+
+bool ossimPlanetCacheTextureLayer::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ bool result = false;
+ if(m_cache.valid())
+ {
+ result = m_cache->hasImage(tileId);
+ }
+ if(!result)
+ {
+ if(m_textureLayer.valid())
+ {
+ result = m_textureLayer->hasTexture(width, height, tileId, grid);
+ }
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetCacheTextureLayer::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ if(!enableFlag())
+ {
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetImage> result;
+ if(m_cache.valid())
+ {
+ result = m_cache->get(tileId);
+ }
+
+ if(!result.valid()&&m_textureLayer.valid())
+ {
+ result = m_textureLayer->getTexture(width, height, tileId, grid, padding);
+
+ if(result.valid()&&m_cache.valid())
+ {
+ m_cache->addOrUpdate(result.get());
+ }
+ }
+ result = applyBrightnessContrast(result.get(), true);
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetCacheTextureLayer::getTexture(ossim_uint32 /* level */,
+ ossim_uint64 /* row */,
+ ossim_uint64 /* col */,
+ const ossimPlanetGridUtility& /* utility */)
+{
+ return 0;
+}
+
+const osg::ref_ptr<ossimPlanetLookAt> ossimPlanetCacheTextureLayer::getLookAt()const
+{
+ return theLookAt.get();
+}
+
+void ossimPlanetCacheTextureLayer::setLookAt(osg::ref_ptr<ossimPlanetLookAt> lookAt)
+{
+ theLookAt = lookAt.get();
+ if(m_textureLayer.valid())
+ {
+ m_textureLayer->setLookAt(lookAt);
+ }
+}
+
+
+void ossimPlanetCacheTextureLayer::getDateRange(ossimDate& minDate,
+ ossimDate& maxDate)const
+{
+ ossimPlanetTextureLayer::getDateRange(minDate, maxDate);
+}
+
+double ossimPlanetCacheTextureLayer::getApproximateHypotneusLength()const
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->getApproximateHypotneusLength();
+ }
+
+ return ossimPlanetTextureLayer::getApproximateHypotneusLength();
+}
+
+void ossimPlanetCacheTextureLayer::getCenterLatLonLength(double& centerLat,
+ double& centerLon,
+ double& length)const
+{
+ if(m_textureLayer.valid())
+ {
+ m_textureLayer->getCenterLatLonLength(centerLat, centerLon, length);
+ }
+
+ ossimPlanetTextureLayer::getCenterLatLonLength(centerLat, centerLon, length);
+
+}
+
+void ossimPlanetCacheTextureLayer::setEnableFlag(bool flag)
+{
+ ossimPlanetTextureLayer::setEnableFlag(flag);
+}
+
+void ossimPlanetCacheTextureLayer::setFilterType(const ossimString& filterType)
+{
+ ossimPlanetTextureLayer::setFilterType(filterType);
+ if(m_textureLayer.valid())
+ {
+ m_textureLayer->setFilterType(filterType);
+ }
+}
+
+void ossimPlanetCacheTextureLayer::getMetadata(ossimRefPtr<ossimXmlNode> metadata)const
+{
+ if(m_textureLayer.valid())
+ {
+ m_textureLayer->getMetadata(metadata.get());
+ }
+}
+
+ossimRefPtr<ossimXmlNode> ossimPlanetCacheTextureLayer::saveXml(bool recurseFlag)const
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->saveXml(recurseFlag);
+ }
+
+ return 0;
+}
+
+bool ossimPlanetCacheTextureLayer::loadXml(ossimRefPtr<ossimXmlNode> node)
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->loadXml(node.get());
+ }
+
+ return false;
+
+}
+
+void ossimPlanetCacheTextureLayer::resetLookAt()
+{
+ if(m_textureLayer.valid())
+ {
+ m_textureLayer->resetLookAt();
+ theLookAt = m_textureLayer->getLookAt();
+ }
+
+}
+
+ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::findLayerByName(const ossimString& layerName,
+ bool recurseFlag)
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->findLayerByName(layerName, recurseFlag);
+ }
+
+ return 0;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::findLayerByName(const ossimString& layerName,
+ bool recurseFlag)const
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->findLayerByName(layerName, recurseFlag);
+ }
+
+ return 0;
+
+}
+
+ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId)
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->findLayerByNameAndId(layerName, layerId);
+ }
+
+ return 0;
+
+}
+
+const ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& layerId)const
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->findLayerByNameAndId(layerName, layerId);
+ }
+
+ return 0;
+
+}
+
+ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::findLayerById(const ossimString& layerId,
+ bool recurseFlag)
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->findLayerById(layerId, recurseFlag);
+ }
+
+ return 0;
+
+}
+
+const ossimPlanetTextureLayer* ossimPlanetCacheTextureLayer::findLayerById(const ossimString& layerId,
+ bool recurseFlag)const
+{
+ if(m_textureLayer.valid())
+ {
+ return m_textureLayer->findLayerById(layerId, recurseFlag);
+ }
+
+ return 0;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetClientThread.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetClientThread.cpp
new file mode 100644
index 0000000..868cd66
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetClientThread.cpp
@@ -0,0 +1,360 @@
+#include <ossimPlanet/ossimPlanetClientThread.h>
+#include <iostream>
+#include <algorithm>
+
+ossimPlanetClientConnection::ossimPlanetClientConnection(SGSocket* socket,
+ ossim_uint32 queueSize)
+ :theSocket(socket),
+ theMaxQueueSize(queueSize)
+{
+}
+
+ossimPlanetClientConnection::ossimPlanetClientConnection()
+ :theSocket(0),
+ theMaxQueueSize(1024)
+{
+}
+
+ossimPlanetClientConnection::~ossimPlanetClientConnection()
+{
+ if(theSocket)
+ {
+ theSocket->close();
+ delete theSocket;
+ theSocket = 0;
+ }
+ theMessageQueue.clear();
+}
+
+
+ossimString ossimPlanetClientConnection::getHost()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimString result;
+ if(theSocket)
+ {
+ result = theSocket->get_hostname();
+ }
+
+ return result;
+}
+
+ossimString ossimPlanetClientConnection::getPortString()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimString result;
+
+ if(theSocket)
+ {
+ result = theSocket->get_port_str();
+ }
+
+ return result;
+}
+
+ossimString ossimPlanetClientConnection::getPortType()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimString result;
+
+ if(theSocket)
+ {
+ result = theSocket->get_port_style();
+ }
+
+ return result;
+}
+
+void ossimPlanetClientConnection::getConnection(ossimString& host,
+ ossimString& port,
+ ossimString& portType)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ if(theSocket)
+ {
+ host = theSocket->get_hostname();
+ port = theSocket->get_port_str();
+ portType = theSocket->get_port_style();
+ }
+}
+
+bool ossimPlanetClientConnection::setConnection(const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ bool result = false;
+
+ if(theSocket)
+ {
+ theSocket->setSocket(host, port, portType);
+ result = theSocket->open(SG_IO_OUT);
+ }
+
+ return result;
+}
+
+void ossimPlanetClientConnection::addMessage(const ossimString& message)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageQueueMutex);
+ if(theSocket)
+ {
+ theMessageQueue.push_back(message);
+ if(theMessageQueue.size() >= theMaxQueueSize)
+ {
+ theMessageQueue.pop_front();
+ }
+ }
+}
+
+void ossimPlanetClientConnection::sendNextMessage()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(theMessageQueueMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(theMutex);
+
+ if(!theMessageQueue.empty()&&theSocket)
+ {
+ ossimString message = popMessage();
+ theSocket->writestring(message.c_str());
+ }
+}
+
+bool ossimPlanetClientConnection::hasMessages()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageQueueMutex);
+
+ return !theMessageQueue.empty();
+}
+
+void ossimPlanetClientConnection::clearQueue()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageQueueMutex);
+ theMessageQueue.clear();
+}
+
+ossimString ossimPlanetClientConnection::popMessage()
+{
+ ossimString result;
+
+ if(!theMessageQueue.empty())
+ {
+ result = theMessageQueue.front();
+ theMessageQueue.pop_front();
+ }
+
+ return result;
+}
+
+SGSocket* ossimPlanetClientConnection::getSocket()
+{
+ return theSocket;
+}
+
+void ossimPlanetClientConnection::setSocket(SGSocket* socket)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(theSocket != socket)
+ {
+ theSocket->close();
+ delete theSocket;
+
+ theSocket = socket;
+ }
+}
+
+ossimPlanetClientThread::ossimPlanetClientThread()
+ :theStartedFlag(false),
+ theDoneFlag(false)
+{
+ theBlock = new ossimPlanetRefBlock();
+}
+
+ossimPlanetClientThread::~ossimPlanetClientThread()
+{
+
+}
+
+void ossimPlanetClientThread::run()
+{
+ if(theStartedFlag) return;
+
+ ossim_uint32 idx = 0;
+ theStartedFlag = true;
+ theDoneFlag = false;
+ while(!theDoneFlag)
+ {
+ theBlock->block();
+ if(theDoneFlag) return;
+ bool hasMessages = false;
+ theConnectionListMutex.lock();
+ for(idx = 0; idx < theClientConnectionList.size(); ++idx)
+ {
+ if(theClientConnectionList[idx]->hasMessages())
+ {
+ theClientConnectionList[idx]->sendNextMessage();
+ hasMessages = true;
+ }
+ }
+ if(!hasMessages)
+ {
+ theBlock->set(false);
+ }
+ theConnectionListMutex.unlock();
+ YieldCurrentThread();
+ }
+
+ theStartedFlag = false;
+}
+
+int ossimPlanetClientThread::cancel()
+{
+ theDoneFlag = true;
+ theBlock->release();
+ return OpenThreads::Thread::cancel();
+}
+
+osg::ref_ptr<ossimPlanetClientConnection> ossimPlanetClientThread::newConnection(const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType)
+{
+ SGSocket* socket = new SGSocket(host, port, portType);
+ socket->open(SG_IO_OUT);
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ osg::ref_ptr<ossimPlanetClientConnection> connection = new ossimPlanetClientConnection(socket);
+ theClientConnectionList.push_back(connection.get());
+
+ return connection.get();
+}
+
+bool ossimPlanetClientThread::setConnection(ossim_uint32 idx,
+ const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ if(idx < theClientConnectionList.size())
+ {
+ return theClientConnectionList[idx]->setConnection(host, port, portType);
+ }
+
+ return false;
+}
+
+void ossimPlanetClientThread::removeConnection(osg::ref_ptr<ossimPlanetClientConnection> connection)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ ossimPlanetClientThreadConnectionList::iterator iter = std::find(theClientConnectionList.begin(),
+ theClientConnectionList.end(),
+ connection.get());
+ if(iter != theClientConnectionList.end())
+ {
+ theClientConnectionList.erase(iter);
+ }
+}
+
+osg::ref_ptr<ossimPlanetClientConnection> ossimPlanetClientThread::removeConnection(ossim_uint32 idx)
+{
+ osg::ref_ptr<ossimPlanetClientConnection> result;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ if(idx < theClientConnectionList.size())
+ {
+ result = theClientConnectionList[idx];
+ theClientConnectionList.erase(theClientConnectionList.begin() + idx);
+ }
+
+ return result;
+}
+
+
+const osg::ref_ptr<ossimPlanetClientConnection> ossimPlanetClientThread::getConnection(ossim_uint32 idx)const
+{
+ osg::ref_ptr<ossimPlanetClientConnection> result;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ if(idx < theClientConnectionList.size())
+ {
+ result = theClientConnectionList[idx];
+ }
+
+ return result;
+}
+
+
+void ossimPlanetClientThread::sendMessage(ossim_uint32 idx,
+ const ossimString& message)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ protectedSendMessage(idx, message);
+
+ if(theStartedFlag)
+ {
+ protectedUpdateClientThreadBlock();
+ }
+ else
+ {
+ start();
+ }
+}
+
+void ossimPlanetClientThread::protectedSendMessage(ossim_uint32 idx,
+ const ossimString& message)
+{
+ if(idx < theClientConnectionList.size())
+ {
+ theClientConnectionList[idx]->addMessage(message);
+
+ }
+}
+
+void ossimPlanetClientThread::broadcastMessage(const ossimString& message)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ ossim_uint32 idx;
+ for(idx = 0; idx < theClientConnectionList.size();++idx)
+ {
+ protectedSendMessage(idx, message);
+ }
+
+ if(theStartedFlag)
+ {
+ protectedUpdateClientThreadBlock();
+ }
+ else
+ {
+ start();
+ }
+}
+
+ossim_uint32 ossimPlanetClientThread::getNumberOfConnections()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ return theClientConnectionList.size();
+}
+
+void ossimPlanetClientThread::updateClientThreadBlock()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theConnectionListMutex);
+ protectedUpdateClientThreadBlock();
+}
+
+void ossimPlanetClientThread::protectedUpdateClientThreadBlock()
+{
+ if(!theStartedFlag) return;
+ bool blockFlag = false;
+
+ if(theClientConnectionList.size() > 0)
+ {
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theClientConnectionList.size(); ++idx)
+ {
+ if(theClientConnectionList[idx]->hasMessages())
+ {
+ blockFlag = true;
+ break;
+ }
+ }
+ }
+ theBlock->set(blockFlag);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetCloudLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetCloudLayer.cpp
new file mode 100644
index 0000000..15b2a9c
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetCloudLayer.cpp
@@ -0,0 +1,666 @@
+#include <ossimPlanet/ossimPlanetCloudLayer.h>
+#include <osg/MatrixTransform>
+#include <osg/Geometry>
+#include <osg/TexMat>
+#include <osg/io_utils>
+#include <osgUtil/CullVisitor>
+#include <osgUtil/IntersectVisitor>
+#include <osgUtil/IntersectionVisitor>
+#include <queue>
+#include <ossim/base/ossimCommon.h>
+
+ossimPlanetCloudLayer::ossimPlanetCloudLayer()
+:theHeading(0.0),
+theSpeed(0.0),
+theTextureTranslation(0.0,0.0,0.0),
+theTextureScale(1.0,1.0,1.0),
+theAutoUpdateTextureMatrixFlag(true),
+theTextureWidth(0),
+theTextureHeight(0),
+theMeshLevel(0),
+theApproximateMetersPerPixelCoverage(90000.0),// lets just init to a big coverage for cloud
+theMaxAltitudeToShowClouds(9999999999999.0)// lets just init to a big coverage for cloud
+{
+ init();
+}
+
+void ossimPlanetCloudLayer::traverse(osg::NodeVisitor& nv)
+{
+ if(dynamic_cast<osgUtil::IntersectVisitor*> (&nv) ||
+ dynamic_cast<osgUtil::IntersectionVisitor*> (&nv)||
+ !enableFlag())
+ {
+ return;
+ }
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ updateTextureMatrix(nv.getFrameStamp()->getSimulationTime());
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(cv)
+ {
+ osg::Vec3d eye = cv->getEyePoint();
+ if(theModel.valid())
+ {
+ osg::Vec3d llh;
+ theModel->xyzToLatLonHeight(eye, llh);
+ if(llh[2] > theMaxAltitudeToShowClouds)
+ {
+ return;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ ossimPlanetLayer::traverse(nv);
+}
+
+void ossimPlanetCloudLayer::init()
+{
+ theGrid = new ossimPlanetAdjustableCubeGrid(ossimPlanetAdjustableCubeGrid::HIGH_CAP);
+ getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
+ getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ setNodeMask(0xffffffff);
+ theTexture = new osg::Texture2D;
+ theTexture->setResizeNonPowerOfTwoHint(false);
+ theTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
+ theTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
+ theTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::REPEAT);
+ theTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT);
+ theTexture->setDataVariance(osg::Object::DYNAMIC);
+ theTexture->setUnRefImageDataAfterApply(false);
+ getOrCreateStateSet()->setTextureAttributeAndModes(0,
+ theTexture.get(),
+ osg::StateAttribute::ON);
+}
+
+void ossimPlanetCloudLayer::splitTiles(ossimPlanetGrid::TileIds& tiles, ossim_uint32 levels)const
+{
+ if(levels == 0) return;
+ std::queue<ossimPlanetTerrainTileId> workQueue;
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < tiles.size(); ++idx)
+ {
+ if(!theGrid->isPolar(tiles[idx]))
+ {
+ workQueue.push(tiles[idx]);
+ }
+ }
+ tiles.clear();
+ ossimPlanetTerrainTileId quad00;
+ ossimPlanetTerrainTileId quad10;
+ ossimPlanetTerrainTileId quad11;
+ ossimPlanetTerrainTileId quad01;
+ ossimPlanetTerrainTileId currentTile;
+ while(!workQueue.empty())
+ {
+ currentTile = workQueue.front();
+ workQueue.pop();
+ currentTile.splitQuad(quad00, quad10, quad11, quad01);
+ if(currentTile.level()+1 >= levels)
+ {
+ tiles.push_back(quad00);
+ tiles.push_back(quad10);
+ tiles.push_back(quad11);
+ tiles.push_back(quad01);
+ }
+ else
+ {
+ workQueue.push(quad00);
+ workQueue.push(quad10);
+ workQueue.push(quad11);
+ workQueue.push(quad01);
+ }
+ }
+}
+
+void ossimPlanetCloudLayer::updateTexture(osg::Image* cloudTexture)
+{
+ theTexture->setImage(cloudTexture);
+ if(cloudTexture)
+ {
+ theTextureWidth = cloudTexture->s();
+ theTextureHeight = cloudTexture->t();
+ updateMetersPerPixelCoverage();
+ }
+ else
+ {
+ theTextureWidth = 0;
+ theTextureHeight = 0;
+ }
+}
+
+void ossimPlanetCloudLayer::updateTexture(ossim_int64 seed,
+ ossim_int32 coverage,
+ ossim_float64 sharpness)
+{
+ osg::ref_ptr<ossimPlanetCloud> cloud = new ossimPlanetCloud;
+ srand(seed);
+ cloud->makeCloud(seed, coverage, sharpness);
+ updateTexture(cloud->image());
+}
+
+void ossimPlanetCloudLayer::computeMesh(double patchAltitude,
+ ossim_uint32 patchWidth,
+ ossim_uint32 patchHeight,
+ ossim_uint32 level)
+{
+ if(!theModel.valid()) return;
+ theGeometryArray.clear();
+ theCenterLlh = osg::Vec3d(0.0,0.0,patchAltitude);
+ ossim_uint32 adjustedWidth = patchWidth;
+ ossim_uint32 adjustedHeight = patchHeight;
+ double adjustedAltitude = patchAltitude;
+ bool patchFlag = false;
+ if(dynamic_cast<Patch*> (theGrid.get()))
+ {
+ if(level > 0)
+ {
+ adjustedWidth <<= level;
+ adjustedHeight <<= level;
+ }
+ // can only do single level meshes with a local patch
+ theMeshLevel = 0;
+ adjustedAltitude = 0;
+ patchFlag = true;
+ }
+ ossimPlanetGrid::ModelPoint modelPoint;
+ ossim_uint32 numCols = adjustedWidth|1; // make sure it's odd
+ ossim_uint32 numRows = adjustedHeight|1; // make sure it's odd
+ ossim_uint32 numberOfPoints = numCols*numRows;
+ bool exceedsUshort = numberOfPoints >= 0x1111;
+ ossimPlanetGrid::TileIds tileIds;
+ theGrid->getRootIds(tileIds);
+ if(theMeshLevel != 0)
+ {
+ splitTiles(tileIds, theMeshLevel);
+ }
+ if(getNumChildren())
+ {
+ removeChildren(0, getNumChildren());
+ }
+ ossim_uint32 idx = 0;
+ double modelHeight = adjustedAltitude*theModel->getInvNormalizationScale();
+ for(idx = 0; idx < tileIds.size();++idx)
+ {
+ if(theGrid->isPolar(tileIds[idx]))
+ {
+ continue;
+ }
+ ossimPlanetTerrainTileId& tileId = tileIds[idx];
+ osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
+ osg::ref_ptr<osg::Geode> geode = new osg::Geode;
+ osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
+
+ osg::Matrixd localToWorld;
+ theModel->lsrMatrix(osg::Vec3d(modelPoint.y(),
+ modelPoint.x(),
+ adjustedAltitude),
+ localToWorld);
+ osg::Matrixd inverseLocalToWorld;
+ inverseLocalToWorld.invert(localToWorld);
+ transform->addChild(geode.get());
+ geode->addDrawable(geometry.get());
+ unsigned int numVerticesInBody = numCols*numRows;
+ unsigned int numVertices = numVerticesInBody;
+
+ osg::ref_ptr<osg::Vec2Array> tcoords = new osg::Vec2Array;
+ tcoords->reserve(numVertices);
+ geometry->setTexCoordArray( 0, tcoords.get());
+
+ osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
+ vertices->reserve(numVertices);
+ geometry->setVertexArray(vertices.get());
+
+ // allocate and assign normals
+ osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
+ if (normals.valid()) normals->reserve(numVertices);
+ geometry->setNormalArray(normals.get());
+ geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+
+ // allocate and assign color
+ osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
+ (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
+
+ geometry->setColorArray(colors.get());
+ geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ theGeometryArray.push_back(geometry.get());
+ ossimPlanetGrid::LocalNdcPoint localPoint;
+ typedef std::vector<int> Indices;
+ Indices indices(numVertices, -1);
+ osg::Vec3d xyz;
+ osg::Vec3d localXyz;
+ osg::Vec3d norm1;
+ ossim_uint32 baseIdx = 0;
+ unsigned int iv = 0;
+ double txInc = 1.0/(numCols-1.0);
+ double tyInc = 1.0/(numRows-1.0);
+ double ty = 0.0;
+ ossim_uint32 colIdx, rowIdx;
+ localPoint.setZ(modelHeight);
+ for(rowIdx = 0; rowIdx < numRows;++rowIdx)
+ {
+ double tx = 0.0;
+ localPoint.setY(ty);//(double)(rowIdx)/(double)(numRows-1));
+ for(colIdx = 0; colIdx < numCols;++colIdx)
+ {
+ //rowIdx*numCols + colIdx;
+ indices[iv] = vertices->size();
+ localPoint.setX(tx);
+ tcoords->push_back(osg::Vec2d(tx, ty));
+ theGrid->localNdcToModel(tileId, localPoint, modelPoint);
+ osg::Vec3d llh(modelPoint.y(), modelPoint.x(), adjustedAltitude);
+ theModel->latLonHeightToXyz(llh, xyz);
+ localXyz = xyz*inverseLocalToWorld;
+ (*vertices).push_back(localXyz);
+ theModel->normal(xyz, norm1);
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ (*normals).push_back(norm1);
+ ++iv;
+ tx+=txInc;
+ }
+ ty += tyInc;
+ }
+ transform->setMatrix(localToWorld);
+
+ if(!exceedsUshort)
+ {
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES));
+ osg::Geometry::PrimitiveSetList primSetList;
+ ossim_uint32 i = 0;
+ ossim_uint32 j = 0;
+ for(i = 1; i < numRows;i+=2)
+ {
+ for(j = 1; j < numCols;j+=2)
+ {
+ ossim_uint32 i00 = (i)*numCols + j;
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols+1));
+ drawElements.push_back(i00 - (numCols));
+
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols));
+ drawElements.push_back(i00 - (numCols-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols-1));
+ drawElements.push_back(i00 + 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + 1);
+ drawElements.push_back(i00 + (numCols+1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols+1));
+ drawElements.push_back(i00 + (numCols));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols));
+ drawElements.push_back(i00 + (numCols-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols-1));
+ drawElements.push_back(i00 - 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - 1);
+ drawElements.push_back(i00 - (numCols+1));
+ }
+ }
+ primSetList.push_back(&drawElements);
+ geometry->setPrimitiveSetList(primSetList);
+ }
+ else
+ {
+ osg::DrawElementsUInt& drawElements = *(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES));
+ osg::Geometry::PrimitiveSetList primSetList;
+ ossim_uint32 i = 0;
+ ossim_uint32 j = 0;
+ for(i = 1; i < numRows;i+=2)
+ {
+ for(j = 1; j < numCols;j+=2)
+ {
+ ossim_uint32 i00 = (i)*numCols + j;
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols+1));
+ drawElements.push_back(i00 - (numCols));
+
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols));
+ drawElements.push_back(i00 - (numCols-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols-1));
+ drawElements.push_back(i00 + 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + 1);
+ drawElements.push_back(i00 + (numCols+1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols+1));
+ drawElements.push_back(i00 + (numCols));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols));
+ drawElements.push_back(i00 + (numCols-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols-1));
+ drawElements.push_back(i00 - 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - 1);
+ drawElements.push_back(i00 - (numCols+1));
+ }
+ }
+ primSetList.push_back(&drawElements);
+ geometry->setPrimitiveSetList(primSetList);
+ }
+ //osgUtil::Simplifier simplifier(.8);
+ //simplifier.simplify(*geometry, pointsToProtect);
+ geometry->dirtyBound();
+ geometry->getBound();
+
+ addChild(transform.get());
+ }
+ theTextureScale[0] = 1.0;
+ theTextureScale[1] = 1.0;
+ theTextureScale[2] = 1.0;
+ theTextureMatrixAttribute = new osg::TexMat();
+ updateTextureMatrix();
+ updateMetersPerPixelCoverage();
+ getOrCreateStateSet()->setTextureAttributeAndModes(0, theTextureMatrixAttribute.get(), osg::StateAttribute::ON);
+
+ if(patchFlag)
+ {
+ moveToLocationLatLonAltitude(theCenterLlh);
+ }
+}
+
+void ossimPlanetCloudLayer::setAlphaValue(float alpha)
+{
+ geometryPtr* geometryArray = &theGeometryArray.front();
+ ossim_uint32 length = theGeometryArray.size();
+
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < length;++idx)
+ {
+ osg::Vec4Array* colors = (osg::Vec4Array*)((*geometryArray)->getColorArray());
+ (*colors)[0].set(1.0f,1.0f,1.0f,alpha);
+
+ // we will let osg dirty and initialize internls s set it back on the geometry
+ (*geometryArray)->setColorArray(colors);
+ ++geometryArray;
+ }
+}
+
+void ossimPlanetCloudLayer::moveToLocationLatLonAltitude(const osg::Vec3d& llh)
+{
+ if(getNumChildren()==1)
+ {
+ osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(getChild(0));
+ if(mt)
+ {
+ osg::Vec3d newLlh = llh;
+ osg::Matrixd localToWorld;
+ theModel->mslToEllipsoidal(newLlh);
+ theModel->lsrMatrix(newLlh,
+ localToWorld);
+ mt->setMatrix(localToWorld);
+ theCenterLlh = newLlh;
+ }
+ }
+}
+
+void ossimPlanetCloudLayer::updateTextureMatrix(double timeScale)
+{
+ if(!theAutoUpdateTextureMatrixFlag) return;
+ if((theTextureHeight>0)&&
+ (!ossim::almostEqual(theSpeed, 0.0)))
+ {
+ double distance = (((theSpeed*timeScale)/theApproximateMetersPerPixelCoverage))/theTextureHeight;
+ theTextureTranslation = ((osg::Vec3d(0.0,1.0,0.0)*
+ osg::Matrixd::rotate(osg::DegreesToRadians(-theHeading),
+ osg::Vec3d(0.0, 0.0, 1.0)))*
+ (-distance));
+ }
+ else
+ {
+ theTextureTranslation = osg::Vec3d(0.0,0.0,0.0);
+ }
+ theTextureMatrix = osg::Matrixd::scale(theTextureScale);
+ theTextureMatrix(3,0) = theTextureTranslation[0];
+ theTextureMatrix(3,1) = theTextureTranslation[1];
+ theTextureMatrix(3,2) = theTextureTranslation[2];
+
+ if(theTextureMatrixAttribute.valid())
+ {
+ theTextureMatrixAttribute->setMatrix(theTextureMatrix);
+ }
+}
+
+void ossimPlanetCloudLayer::updateMetersPerPixelCoverage()
+{
+ if(theTextureHeight>0)
+ {
+ double factor = 1.0;
+ if(theMeshLevel)
+ {
+ factor /=(ossim_float64)(1<<theMeshLevel);
+
+ }
+ theApproximateMetersPerPixelCoverage = ((90.0*factor)/(theTextureScale[1]*theTextureHeight))*ossimGpt().metersPerDegree().y;
+ }
+}
+
+void ossimPlanetCloudLayer::setMaxAltitudeToShowClouds(ossim_float64 maxAltitude)
+{
+ theMaxAltitudeToShowClouds = maxAltitude;
+}
+
+ossim_float64 ossimPlanetCloudLayer::maxAltitudeToShowClouds()const
+{
+ return theMaxAltitudeToShowClouds;
+}
+
+void ossimPlanetCloudLayer::setTextureMatrix(osg::TexMat* texMatrix)
+{
+ if((theTextureMatrixAttribute.get()!=texMatrix)&&
+ (texMatrix))
+ {
+ theTextureMatrixAttribute = texMatrix;
+ theTextureMatrix = texMatrix->getMatrix();
+ getOrCreateStateSet()->setTextureAttributeAndModes(0, theTextureMatrixAttribute.get(), osg::StateAttribute::ON);
+ }
+
+}
+
+ossimPlanetCloud::ossimPlanetCloud(TextureSize size)
+{
+ switch(size)
+ {
+ case TEXTURE_SIZE_256_256:
+ {
+ theCloudDataWidth=theCloudDataHeight=256;
+ theNoiseDataWidth=theNoiseDataHeight=32;
+ break;
+ }
+ case TEXTURE_SIZE_512_512:
+ {
+ theCloudDataWidth=theCloudDataHeight=512;
+ theNoiseDataWidth=theNoiseDataHeight=64;
+ break;
+ }
+ case TEXTURE_SIZE_1024_1024:
+ {
+ theCloudDataWidth=theCloudDataHeight=1024;
+ theNoiseDataWidth=theNoiseDataHeight=128;
+ break;
+ }
+ case TEXTURE_SIZE_2048_2048:
+ {
+ theCloudDataWidth=theCloudDataHeight=2048;
+ theNoiseDataWidth=theNoiseDataHeight=256;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ theCloudData.resize(theCloudDataWidth*theCloudDataHeight);
+ theNoise.resize(theNoiseDataWidth*theNoiseDataHeight);
+}
+
+double ossimPlanetCloud::noise(ossim_int32 x, ossim_int32 y, ossim_int32 random)const
+{
+ ossim_int32 n = x + y * 57 + random * 131;
+ n = (n<<13) ^ n;
+ return (1.0 - ( (n * (n * n * 15731 + 789221) +
+ 1376312589)&0x7fffffff)* 0.000000000931322574615478515625);
+}
+void ossimPlanetCloud::makeNoise(ossim_int64 seed)
+{
+ srand(seed);
+ std::vector<std::vector<ossim_float64> > temp;
+// ossim_float64 temp[theNoiseDataWidth+2][theNoiseDataHeight+2];
+ ossim_float64* noiseMap = &theNoise.front();
+ ossim_int32 random=rand() % 100000;
+ temp.resize(theNoiseDataHeight+2);
+ temp[0].resize(theNoiseDataWidth+2);
+ temp[theNoiseDataHeight+1].resize(theNoiseDataWidth+2);
+ for (int y=1; y<(theNoiseDataHeight+1); y++)
+ {
+ temp[y].resize(theNoiseDataWidth+2);
+ for (int x=1; x<(theNoiseDataWidth+1); x++)
+ {
+ temp[y][x] = 128.0 + noise(x, y, random)*128.0;
+ //temp[x][y] = 128.0 + noise(x, y, random)*128.0;
+ }
+ }
+ for (int x=1; x<(theNoiseDataWidth+1); x++)
+ {
+ temp[x][0] = temp[x][theNoiseDataWidth];
+ temp[x][theNoiseDataWidth+1] = temp[x][1];
+ temp[0][x] = temp[theNoiseDataHeight][x];
+ temp[theNoiseDataWidth+1][x] = temp[1][x];
+ }
+ temp[0][0] = temp[theNoiseDataHeight][theNoiseDataWidth];
+ temp[theNoiseDataWidth+1][theNoiseDataHeight+1] = temp[1][1];
+ temp[theNoiseDataHeight+1][0] = temp[1][theNoiseDataWidth];
+ temp[0][theNoiseDataWidth+1] = temp[theNoiseDataHeight][1];
+ for (int y=1; y<(theNoiseDataHeight+1); y++)
+ {
+ for (int x=1; x<(theNoiseDataWidth+1); x++)
+ {
+ ossim_float64 center = temp[y][x]/4.0;
+ ossim_float64 sides = (temp[y][x+1] + temp[y][x-1] + temp[y+1][x] + temp[y-1][x])/8.0;
+ ossim_float64 corners = (temp[y+1][x+1] + temp[y-1][x+1] + temp[y+1][x-1] + temp[y-1][x-1])/16.0;
+
+ noiseMap[((x-1)*theNoiseDataWidth) + (y-1)] = center + sides + corners;
+ }
+ }
+}
+ossim_float64 ossimPlanetCloud::interpolate(ossim_float64 x, ossim_float64 y, ossim_float64 *map)
+{
+ int Xint = (int)x;
+ int Yint = (int)y;
+
+ ossim_float64 Xfrac = x - Xint;
+ ossim_float64 Yfrac = y - Yint;
+ int X0 = Xint % theNoiseDataWidth;
+ int Y0 = Yint % theNoiseDataHeight;
+ int X1 = (Xint + 1) % theNoiseDataWidth;
+ int Y1 = (Yint + 1) % theNoiseDataHeight;
+ ossim_float64 bot = map[X0*theNoiseDataWidth + Y0] + Xfrac * (map[X1*theNoiseDataWidth + Y0] - map[X0*theNoiseDataWidth + Y0]);
+ ossim_float64 top = map[X0*theNoiseDataWidth + Y1] + Xfrac * (map[X1*theNoiseDataWidth + Y1] - map[X0*theNoiseDataWidth + Y1]);
+
+ return (bot + Yfrac * (top - bot));
+}
+void ossimPlanetCloud::overlapOctaves()
+{
+ ossim_float64 *mapNoise = &theNoise.front();
+ ossim_float64 *mapCloud = &theCloudData.front();
+ ossim_uint32 cloudArea = theCloudDataWidth*theCloudDataHeight;
+ ossim_int32 x,y, octave;
+ for (x=0; x<cloudArea; x++)
+ {
+ mapCloud[x] = 0;
+ }
+ for (octave=0; octave<4; octave++)
+ {
+ for (x=0; x<theCloudDataWidth; x++)
+ {
+ for (y=0; y<theCloudDataHeight; y++)
+ {
+ ossim_float64 scale = 1 / pow(2.0, 3.0-octave);
+ ossim_float64 noise = interpolate(x*scale, y*scale , mapNoise);
+ mapCloud[(y*theCloudDataWidth) + x] += noise / pow(2.0, (ossim_float64)octave);
+ }
+ }
+ }
+}
+void ossimPlanetCloud::expFilter()
+{
+// std::cout << "sharp = " << theSharpness << std::endl;
+// std::cout << "cov = " << theCoverage << std::endl;
+
+ ossim_float64 *map = &theCloudData.front();
+ for (int x=0; x<theCloudData.size(); x++)
+ {
+ ossim_float64 c = map[x] - (255.0-theCoverage);
+ if (c<0)
+ {
+ c = 0;
+ }
+ map[x] = 255.0 - ((ossim_float64)(pow(theSharpness, c))*255.0);
+ }
+}
+osg::Image* ossimPlanetCloud::image()
+{
+ return theImage.get();
+}
+
+void ossimPlanetCloud::makeCloud(ossim_int64 seed=0, ossim_int32 coverage, ossim_float64 sharpness)
+{
+ theCoverage = coverage;
+ theSharpness = sharpness;
+ ossim_uint32 area = theCloudDataWidth*theCloudDataHeight;
+ unsigned char* newData = new unsigned char[area*4];
+ unsigned char* newDataPtr = newData;
+ ossim_float64* cloudData = &theCloudData.front();
+ makeNoise(seed);
+ overlapOctaves();
+ expFilter();
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ newDataPtr[0] = (ossim_uint8)ossim::clamp((*cloudData), 0.0, 255.0);
+ newDataPtr[1] = newDataPtr[0];
+ newDataPtr[2] = newDataPtr[0];
+ newDataPtr[3] = newDataPtr[0];
+ newDataPtr+=4;
+ ++cloudData;
+ }
+ theImage = new osg::Image();
+ theImage->setImage(theCloudDataWidth, theCloudDataHeight, 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ newData,
+ osg::Image::USE_NEW_DELETE);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetCompass.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetCompass.cpp
new file mode 100644
index 0000000..0278e8e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetCompass.cpp
@@ -0,0 +1,638 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2007, Arizona State University
+// All rights reserved.
+// BSD License: http://www.opensource.org/licenses/bsd-license.html
+// Created by: Jeff Conner
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ossimPlanet/ossimPlanetCompass.h"
+
+
+
+
+
+// #include "Usul/CommandLine/Arguments.h"
+
+#include "osgUtil/CullVisitor"
+
+#include "osgUtil/CullVisitor"
+#include "osgDB/ReadFile"
+#include "osg/MatrixTransform"
+#include "osg/Math"
+#include "osg/Texture2D"
+#include "osg/Image"
+#include "osg/Geometry"
+#include "osg/Geode"
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Update Callback for hiding and showing the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class CompassAnimationCallback : public osg::NodeCallback
+{
+public:
+
+ CompassAnimationCallback(ossimPlanetCompass* compass, float start, float end, float step)
+ {
+ _start = start;
+ _end = end;
+ _step = step;
+ _compass = compass;
+ }
+
+ virtual void operator() (osg::Node* node, osg::NodeVisitor* nv)
+ {
+ osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
+ if(0L != transform)
+ {
+ if(_compass->isAnimating())
+ {
+ if(_compass->isVisible())
+ {
+ if (_start < _end)
+ {
+ _start += _step;
+ if(_start > _end) _start = _end;
+ transform->setMatrix(osg::Matrix::scale(_start,_start,_start));
+
+ }
+ else
+ {
+ _compass->setAnimation(false);
+ }
+ }
+ else
+ {
+ if (_start > _end)
+ {
+ _start -= _step;
+ if(_start < _end) _start = _end;
+ transform->setMatrix(osg::Matrix::scale(_start,_start,_start));
+
+ }
+ else
+ {
+ _compass->setAnimation(false);
+ }
+ }
+ }
+ }
+ traverse(node,nv);
+
+ }
+
+protected:
+
+ osg::ref_ptr<ossimPlanetCompass> _compass;
+ float _angular_velocity;
+ float _start;
+ float _end;
+ float _step;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Cull Callback for rotating the compass based on the current view matrix
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class CompassOrientationCallback : public osg::NodeCallback
+{
+public:
+ CompassOrientationCallback(ossimPlanetCompass *compass) :
+ _scale(.07f)
+ {
+ _compass = compass;
+ _pos = (osg::Vec3(_scale * 4.0f, _scale * -3.0f, -1.0f));
+ theHeadingFlag = true;
+ theRollFlag = true;
+ thePitchFlag = true;
+ }
+ virtual void operator()(osg::Node *node, osg::NodeVisitor *nv)
+ {
+ osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor *>(nv);
+ if( 0L != cv)
+ {
+ osg::MatrixTransform *tx = dynamic_cast<osg::MatrixTransform *>(node);
+ if( 0L != tx )
+ {
+ double h = theHeadingFlag?_compass->heading():0.0;
+ double p = thePitchFlag? _compass->pitch():0.0;
+ double r = theRollFlag?_compass->roll():0.0;
+
+ tx->setMatrix ( osg::Matrix::scale ( _compass->scale(),
+ _compass->scale(),
+ _compass->scale()) *
+ osg::Matrix::rotate ( osg::inDegrees ( h ),
+ 0.0f, 0.0f, 1.0f ) *
+ osg::Matrix::rotate ( osg::inDegrees ( p ),
+ 1.0f, 0.0f, 0.0f ) *
+ osg::Matrix::rotate ( osg::inDegrees ( r ),
+ 0.0f, 0.0f, 1.0f ) * // make it about z as well
+ osg::Matrix::translate ( _compass->position() ) );
+ }
+ }
+ traverse( node, nv );
+ }
+ void setFlags(bool heading, bool pitch, bool roll)
+ {
+ theHeadingFlag = heading;
+ thePitchFlag = pitch;
+ theRollFlag = roll;
+ }
+protected:
+ bool theHeadingFlag;
+ bool theRollFlag;
+ bool thePitchFlag;
+
+ ossimPlanetCompass* _compass;
+ osg::Vec3 _pos;
+ float _scale;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Constructor/Destructor
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ossimPlanetCompass::ossimPlanetCompass():
+ _scale ( .07f ),
+ _numslices ( 32 ),
+ _radius ( .8 ),
+ theCompassGroup ( new osg::Group() ),
+ _showOrHideCompass ( true ),
+ _animating ( false ),
+ _rotateByView ( true ),
+ _heading ( 0.0f ),
+ _pitch ( 0.0f ),
+ _roll(0.0f)
+{
+ theCommonColorArray = new osg::Vec4Array();
+ theCommonColorArray->push_back(osg::Vec4(1.0,1.0,1.0,.5));
+ ossimFilename defaultTop = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ defaultTop = defaultTop.dirCat("images");
+// theRing = defaultTop.dirCat("compassring.png");
+// theInterior = defaultTop.dirCat("compassrose.png");
+
+ this->setPositionByPercentage( 1.0f, 0.0f );
+#if 0
+ if(theCompassFilename.exists())
+ {
+ theCompassObject = this->buildCompassObject(theCompassFilename);
+// theCompassInteriorObject = this->buildCompassObject(theInterior);
+ }
+#endif
+ buildCompass();
+}
+
+ossimPlanetCompass::~ossimPlanetCompass(){}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Return the state of the compass: visible or not
+//
+///////////////////////////////////////////////////////////////////////////////
+
+bool ossimPlanetCompass::isVisible()
+{
+ return _showOrHideCompass;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the texture filename for the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setCompassTexture(const ossimFilename& fn)
+{
+ theCompassFilename = fn;
+ theCompassObject = this->buildCompassObject(theCompassFilename);
+}
+
+//void ossimPlanetCompass::setInterior(const ossimFilename& fn)
+//{
+// theInterior = fn;
+// theCompassInteriorObject = this->buildCompassObject(theInterior);
+//}
+//void ossimPlanetCompass::setInterior(const ossimFilename& fn)
+//{
+// theCompassFilename = fn;
+// theCompassObject = this->buildCompassObject(theCompassFilename);
+//}
+
+//void ossimPlanetCompass::setCompassTexture(const ossimFilename& ring,
+// const ossimFilename& interior)
+//{
+// setRing(ring);
+// setInterior(interior);
+//}
+
+void ossimPlanetCompass::traverse(osg::NodeVisitor& nv)
+{
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ if(theCompassGroup.valid())
+ {
+ theCompassGroup->accept(nv);
+ }
+ osg::Node::traverse(nv);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Get the heading of the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+float ossimPlanetCompass::heading()
+{
+ return _heading;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the heading of the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setHeading(float r)
+{
+ _heading = r;
+}
+
+float ossimPlanetCompass::pitch ( )
+{
+ return _pitch;
+}
+
+void ossimPlanetCompass::setPitch ( float p )
+{
+ _pitch = p;
+}
+
+float ossimPlanetCompass::roll ( )
+{
+ return _roll;
+}
+
+void ossimPlanetCompass::setRoll(float r)
+{
+ _roll = r;
+}
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the heading of the compass based on a ( x = lon, y = lat ) position
+// and a ( x = lon, y = lat ) north.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setHeadingRelativeToNorth(const osg::Vec2& north, const osg::Vec2& pos)
+{
+ //FILE* debug = fopen ("C:/debug.txt","a");
+
+ osg::Vec2f p ( pos.x(), pos.y() );
+
+ /*if( p.x() > 180 )
+ p.set( p.x() - 180.0f , p.y() );*/
+
+ float theta = atan ( ( north.y() - p.y() ) / ( north.x() - p.x() ) );
+
+ //fprintf(debug,"N.x=%f , N.y=%f\tP.x=%f(%f) , P.y=%f\ttheta=%f\n",north.x(),north.y(),pos.x(),p.x(),p.y(),(theta * 180 / osg::PI) );
+ //fclose(debug);
+ this->setHeading( osg::RadiansToDegrees( theta ) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Get the position on the screen of the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+const osg::Vec3& ossimPlanetCompass::position()
+{
+ return _pos;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the position on the screen of the compass by absolute postion
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setPosition(const osg::Vec3& p)
+{
+ _pos = p;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the position on the screen of the compass by percentage of screen
+// Pass in a float value between 0 and 1;
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setPositionByPercentage ( float width, float height )
+{
+ float w = ( _scale * width * 8.0f ) - ( 4.0f * _scale );
+ float h = ( _scale * height * 6.0f ) - ( 3.0f * _scale );
+
+ _pos = osg::Vec3(w, h, -1.0f);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Get the xyz scale value of the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+float ossimPlanetCompass::scale()
+{
+ return _scale;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the xyz scale value of the compass
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setScale(float s)
+{
+ _scale = s;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Return true if the compass is in the act of showing or hiding
+//
+///////////////////////////////////////////////////////////////////////////////
+
+bool ossimPlanetCompass::isAnimating()
+{
+ return _animating;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set the animation state to trigger a show or hide.
+// Use showCompass() or hideCompass() methods.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setAnimation(bool state)
+{
+ _animating = state;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// true to use the view matrix
+// false to use "by angle degree"
+// - set using "setRotation" method.
+// - call "updateCompass" after changing angle values to rebuild
+// the compass
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::setRotateByViewMatrix(bool m)
+{
+ _rotateByView = m;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Rebuilds compass based upon animation show/hide parameters.
+// Call this method to rebuild after changing parameters in a set method
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::updateCompass()
+{
+ if(_showOrHideCompass)
+ buildCompass();
+ if(!_showOrHideCompass && _animating)
+ buildCompass();
+ if(!_showOrHideCompass && !_animating)
+ _emptyCompass();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Build a triangle fan object to use as a compass face
+//
+///////////////////////////////////////////////////////////////////////////////
+
+osg::Geode* ossimPlanetCompass::buildTriangleFan(const ossimFilename& tex, float zoff, unsigned int render_level, const osg::Vec3& n)
+{
+ osg::ref_ptr< osg::Geode > geode ( new osg::Geode() );
+ osg::ref_ptr< osg::StateSet > stateset ( new osg::StateSet() );
+ osg::ref_ptr< osg::Image > image;
+
+ if(tex.exists())
+ {
+ image = osgDB::readImageFile( tex );
+ }
+ if ( image.get() )
+ {
+ osg::ref_ptr< osg::Texture2D > texture ( new osg::Texture2D() );
+ texture->setImage ( image.get() );
+ stateset->setTextureAttributeAndModes ( 0, texture.get(), osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
+ stateset->setMode ( GL_BLEND, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
+ stateset->setMode ( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
+ stateset->setRenderingHint ( osg::StateSet::TRANSPARENT_BIN );
+ stateset->setRenderBinDetails ( render_level, "RenderBin" );
+
+ }
+
+ osg::ref_ptr< osg::Vec3Array > fan ( new osg::Vec3Array() );
+ osg::ref_ptr< osg::Vec2Array > fan_tex ( new osg::Vec2Array() );
+
+ fan->reserve( _numslices +1 );
+ fan_tex->reserve( _numslices +1 );
+
+ fan->push_back( osg::Vec3 ( 0.0f, 0.0f, zoff ) );
+ fan_tex->push_back( osg::Vec2 ( 0.5f, 0.5f ) );
+
+ for ( unsigned int x = 0; x < _numslices + 1; ++x )
+ {
+ float angle = float ( x ) * ( ( 2 * osg::PI ) / _numslices );
+ fan->push_back ( osg::Vec3 ( _radius * ( cos( angle ) ), _radius * ( sin ( angle ) ), zoff ) );
+ fan_tex->push_back(osg::Vec2(0.5f + (0.5f * ( cos( angle ) ) ),0.5f +( 0.5f * ( sin ( angle ) ) ) ));
+ }
+ osg::ref_ptr< osg::Geometry > geometry ( new osg::Geometry() );
+ osg::ref_ptr< osg::Vec3Array > normal = new osg::Vec3Array;
+// osg::ref_ptr< osg::Vec4Array > color ( new osg::Vec4Array() );
+// color->push_back ( osg::Vec4 ( 1.0f, 1.0f, 1.0f, .5f ) );
+ geometry->setColorArray ( theCommonColorArray.get() );
+ geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
+ normal->push_back ( n );
+
+ geometry->setVertexArray ( fan.get() );
+
+ geometry->setTexCoordArray ( 0, fan_tex.get() );
+
+ geometry->setNormalArray ( normal.get() );
+
+ geometry->setNormalBinding ( osg::Geometry::BIND_OVERALL );
+
+ geometry->addPrimitiveSet ( new osg::DrawArrays ( osg::PrimitiveSet::TRIANGLE_FAN, 0, fan->size() ) );
+
+ geometry->setStateSet ( stateset.get() );
+
+ geode->setStateSet ( stateset.get() );
+
+ geode->addDrawable ( geometry.get() );
+
+ return geode.release();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Build the acutal compass object, consisting of 2 textured triangle fans
+//
+///////////////////////////////////////////////////////////////////////////////
+
+osg::Node* ossimPlanetCompass::buildCompassObject(const ossimFilename& location)
+{
+ osg::ref_ptr < osg::Group > group ( new osg::Group() );
+ group->addChild ( this->buildTriangleFan ( location,
+ 0.0f,
+ 1001,
+ osg::Vec3 ( 0.0f, 0.0f, 1.0f ) ) );
+// group->addChild ( this->_buildTriangleFan ( _botTexfn, -0.05f, 1000, osg::Vec3 ( 0.0f, 0.0f, 1.0f ) ) );
+ return group.release();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set matrix transforms for the compass. Add the Cull and update callbacks
+// for rotation and animation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+osg::Group* ossimPlanetCompass::initCompass()
+{
+ osg::ref_ptr<osg::Group> group = new osg::Group;
+ osg::ref_ptr < osg::MatrixTransform > rotRing ( new osg::MatrixTransform() );
+ osg::ref_ptr < osg::MatrixTransform > rotInterior ( new osg::MatrixTransform() );
+ osg::ref_ptr < osg::MatrixTransform > animRing ( new osg::MatrixTransform() );
+ osg::ref_ptr < osg::MatrixTransform > animInterior ( new osg::MatrixTransform() );
+ osg::ref_ptr < CompassOrientationCallback > rotation_callback_ring ( new CompassOrientationCallback ( this ) );
+// osg::ref_ptr < CompassOrientationCallback > rotation_callback_interior ( new CompassOrientationCallback ( this ) );
+
+ rotation_callback_ring->setFlags(true, true, false);
+ //rotation_callback_interior->setFlags(false, true, true);
+ CompassAnimationCallback* animCallback = new CompassAnimationCallback ( this,
+ _animationStart,
+ _animationEnd,
+ _animationStep );
+ animRing->setUpdateCallback ( animCallback );
+ animInterior->setUpdateCallback ( animCallback );
+ rotRing->setCullCallback ( rotation_callback_ring.get() );
+ // rotInterior->setCullCallback ( rotation_callback_interior.get() );
+
+ rotRing->setReferenceFrame ( osg::Transform::ABSOLUTE_RF );
+ //rotInterior->setReferenceFrame ( osg::Transform::ABSOLUTE_RF );
+
+ animRing->addChild ( theCompassObject.get() );
+ // animInterior->addChild ( theCompassInteriorObject.get() );
+ rotRing->addChild ( animRing.get() );
+ //rotInterior->addChild ( animInterior.get() );
+ // group->addChild(rotInterior.get());
+ group->addChild(rotRing.get());
+
+ return group.release();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Remove all children from the compass group. Called when compass is
+// "hidden"
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::_emptyCompass()
+{
+ theCompassGroup->removeChildren ( 0, theCompassGroup->getNumChildren() );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Build the compass.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::buildCompass()
+{
+ osg::ref_ptr < osg::Group > group ( new osg::Group() );
+// osg::ref_ptr < osg::Node > geode = _buildCompassObject();
+
+ osg::ref_ptr < osg::StateSet > ss ( theCompassGroup->getOrCreateStateSet() );
+ ss->setRenderBinDetails ( 1000, "RenderBin" );
+ ss->setMode ( GL_DEPTH_TEST, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
+ ss->setMode ( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::INHERIT );
+
+ theCompassGroup->removeChildren ( 0, theCompassGroup->getNumChildren() );
+ theCompassGroup->addChild ( initCompass ( ) );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set parameters to display the "show" animation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::_showCompass()
+{
+ _animationStart = 0.0f;
+ _animationEnd = 1.0f;
+ _animationStep = 1.0f / 20.0f;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Set parameters to display the "hide" animation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+void ossimPlanetCompass::_hideCompass()
+{
+ _animationStart = 1.0f;
+ _animationEnd = 0.0f;
+ _animationStep = -1 * (1.0f / 20.0f);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetCubeGrid.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetCubeGrid.cpp
new file mode 100644
index 0000000..66cd7f6
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetCubeGrid.cpp
@@ -0,0 +1,221 @@
+#include <ossimPlanet/ossimPlanetCubeGrid.h>
+#include <ossimPlanet/mkUtils.h>
+#include <iostream>
+
+ossim_uint32 ossimPlanetCubeGrid::getNumberOfFaces()const
+{
+ return 6;
+}
+void ossimPlanetCubeGrid::getPixelScale(double& dx,
+ double& dy,
+ ossimUnitType& pixelScaleUnits,
+ ossim_uint32 level,
+ ossim_uint64 /*row*/,
+ ossim_uint64 /*col*/)const
+{
+ dx = 90.0*(1.0/(1<<level));
+ dy = dx;
+ dx/=theTileWidth;
+ dy/=theTileHeight;
+ pixelScaleUnits = OSSIM_DEGREES;
+}
+
+void ossimPlanetCubeGrid::getWidthHeightInDegrees(double& deltaX,
+ double& deltaY,
+ ossim_uint32 level,
+ ossim_uint64 /*row*/,
+ ossim_uint64 /*col*/)const
+{
+ deltaX = (90.0/((double)(1<<level)));
+ deltaY = deltaX;
+}
+
+void ossimPlanetCubeGrid::getGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ const osg::Vec3d& latLon)const
+{
+ osg::Vec2d ll((ossim::clamp((double)latLon[ossimPlanetGridUtility::LAT],
+ (double)-90.0, (double)90.0)+90)/180,
+ (ossim::wrap((double)latLon[ossimPlanetGridUtility::LON],
+ (double)-180.0, (double)180.0)+180)/360);
+ int face_x = (int)(4 * ll[ossimPlanetGridUtility::LON]);
+ int face_y = (int)(2 * ll[ossimPlanetGridUtility::LAT] + 0.5);
+ if(face_x == 4)
+ {
+ face_x = 3;
+ }
+ if(face_y == 1)
+ {
+ gridPoint.theFace = face_x;
+ }
+ else
+ {
+ gridPoint.theFace = face_y < 1 ? 5 : 4;
+ }
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 4 * ll[ossimPlanetGridUtility::LON] - face_x;
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 2 * ll[ossimPlanetGridUtility::LAT] - 0.5;
+ if(gridPoint.theFace < 4) // equatorial calculations done
+ {
+// gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 1-gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ return;
+ }
+
+ double tmp=0.0;
+ if(gridPoint.theFace == 4) // north polar face
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 1.5 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = (2 * (gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] - 0.5) *
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] + 0.5);
+ switch(face_x)
+ {
+ case 0: // bottom
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 0.5 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ break;
+ }
+ case 1: // right side, swap and reverse lat
+ {
+ tmp = gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 0.5 + gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = tmp;
+ break;
+ }
+ case 2: // top; reverse lat and lon
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 1 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 0.5 + gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ break;
+ }
+ case 3: // left side; swap and reverse lon
+ {
+ tmp = gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 0.5 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 1 - tmp;
+ break;
+ }
+ }
+ }
+ else // south polar face
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] += 0.5;
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = (2 * (gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] - 0.5) *
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] + 0.5);
+ switch(face_x)
+ {
+ case 0: // left
+ {
+ tmp = gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 0.5 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = tmp;
+ break;
+ }
+ case 1: // top
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 0.5 + gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ break;
+ }
+ case 2: // right
+ {
+ tmp = gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 0.5 + gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 1 - tmp;
+ break;
+ }
+ case 3: // bottom
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = 1 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX];
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 0.5 - gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ break;
+ }
+ }
+ }
+}
+
+
+void ossimPlanetCubeGrid::getLatLon(osg::Vec3d& latLon,
+ const ossimPlanetGridUtility::GridPoint& gridPoint)const
+{
+ double offset = 0.0;
+ osg::Vec2d s(ossim::clamp(gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX], 0.0, 1.0),
+ ossim::clamp(gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY], 0.0, 1.0));
+ const osg::Vec3d& coord = gridPoint.theGlobalGridPoint;
+ latLon[ossimPlanetGridUtility::HGT] = 0.0;
+ if(gridPoint.theFace < 4)
+ {
+ s[ossimPlanetGridUtility::GRIDX] = (coord[ossimPlanetGridUtility::GRIDX]+gridPoint.theFace)*.25;
+ s[ossimPlanetGridUtility::GRIDY] = (coord[ossimPlanetGridUtility::GRIDY] + 0.5)*0.5;
+// latLon[ossimPlanetGridUtility::LON] = s[ossimPlanetGridUtility::GRIDX]*360.0 - 180.0;
+// latLon[ossimPlanetGridUtility::LAT] = 90 - s[ossimPlanetGridUtility::GRIDY]*180.0;
+// return;
+ }
+ else if(gridPoint.theFace == 4)
+ {
+ if(coord[ossimPlanetGridUtility::GRIDX] < coord[ossimPlanetGridUtility::GRIDY])
+ {
+ if(coord[ossimPlanetGridUtility::GRIDX] + coord[ossimPlanetGridUtility::GRIDY] < 1.0)
+ {
+ s[ossimPlanetGridUtility::GRIDX] = 1.0 - coord[ossimPlanetGridUtility::GRIDY];
+ s[ossimPlanetGridUtility::GRIDY] = coord[ossimPlanetGridUtility::GRIDX];
+ offset += 3;
+ }
+ else
+ {
+ s[ossimPlanetGridUtility::GRIDY] = 1.0 - coord[ossimPlanetGridUtility::GRIDY];
+ s[ossimPlanetGridUtility::GRIDX] = 1.0 - coord[ossimPlanetGridUtility::GRIDX];
+ offset += 2;
+ }
+ }
+ else if(coord[ossimPlanetGridUtility::GRIDX] + coord[ossimPlanetGridUtility::GRIDY] >= 1.0)
+ {
+ s[ossimPlanetGridUtility::GRIDX] = coord[ossimPlanetGridUtility::GRIDY];
+ s[ossimPlanetGridUtility::GRIDY] = 1.0 - coord[ossimPlanetGridUtility::GRIDX];
+ offset += 1.0;
+ }
+ s[ossimPlanetGridUtility::GRIDX] -= s[ossimPlanetGridUtility::GRIDY];
+ if(!ossim::almostEqual(s[ossimPlanetGridUtility::GRIDY], .5))
+ {
+ s[ossimPlanetGridUtility::GRIDX] *= .5/(.5 - s[ossimPlanetGridUtility::GRIDY]);
+ }
+ s[ossimPlanetGridUtility::GRIDX] = (s[ossimPlanetGridUtility::GRIDX] + offset)*0.25;
+ s[ossimPlanetGridUtility::GRIDY] = (s[ossimPlanetGridUtility::GRIDY] + 1.5)*.5;
+ }
+ else if(gridPoint.theFace == 5)
+ {
+ offset = 1.0;
+ if(coord[ossimPlanetGridUtility::GRIDX] > coord[ossimPlanetGridUtility::GRIDY])
+ {
+ if(coord[ossimPlanetGridUtility::GRIDX] + coord[ossimPlanetGridUtility::GRIDY] >= 1.0)
+ {
+ s[ossimPlanetGridUtility::GRIDX] = 1.0 - coord[ossimPlanetGridUtility::GRIDY];
+ s[ossimPlanetGridUtility::GRIDY] = coord[ossimPlanetGridUtility::GRIDX] - .5;
+ offset += 1.0;
+ }
+ else
+ {
+ s[ossimPlanetGridUtility::GRIDX] = 1.0 - coord[ossimPlanetGridUtility::GRIDX];
+ s[ossimPlanetGridUtility::GRIDY] = 0.5 - coord[ossimPlanetGridUtility::GRIDY];
+ offset+=2;
+ }
+ }
+ else
+ {
+ if(coord[ossimPlanetGridUtility::GRIDX] + coord[ossimPlanetGridUtility::GRIDY] < 1.0)
+ {
+ s[ossimPlanetGridUtility::GRIDX] = coord[ossimPlanetGridUtility::GRIDY];
+ s[ossimPlanetGridUtility::GRIDY] = 0.5 - coord[ossimPlanetGridUtility::GRIDX];
+ offset -= 1.0;
+ }
+ else
+ {
+ s[ossimPlanetGridUtility::GRIDY] = coord[ossimPlanetGridUtility::GRIDY] - 0.5;
+ }
+ }
+ if(!ossim::almostEqual((double)s[ossimPlanetGridUtility::GRIDY], (double)0.0))
+ {
+ s[ossimPlanetGridUtility::GRIDX] = (s[ossimPlanetGridUtility::GRIDX] - 0.5)*.5/s[ossimPlanetGridUtility::GRIDY] + .5;
+ }
+ s[ossimPlanetGridUtility::GRIDX] = (s[ossimPlanetGridUtility::GRIDX] + offset) *0.25;
+ s[ossimPlanetGridUtility::GRIDY] *=.5;
+ }
+ latLon[ossimPlanetGridUtility::LON] = s[ossimPlanetGridUtility::GRIDX]*360.0 - 180.0;
+ latLon[ossimPlanetGridUtility::LAT] = s[ossimPlanetGridUtility::GRIDY]*180.0 - 90.0;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetDatabasePager.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetDatabasePager.cpp
new file mode 100644
index 0000000..9bc4c53
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetDatabasePager.cpp
@@ -0,0 +1,583 @@
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+
+
+
+ossimPlanetDatabasePager::ossimPlanetDatabasePager()
+:DatabasePager()
+{
+}
+#if 0
+bool ossimPlanetDatabasePager::isRunning() const
+{
+ return DatabasePager::isRunning();
+}
+
+void ossimPlanetDatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp)
+{
+ DatabasePager::signalBeginFrame(framestamp);
+}
+
+void ossimPlanetDatabasePager::signalEndFrame()
+{
+ DatabasePager::signalEndFrame();
+}
+
+void ossimPlanetDatabasePager::updateSceneGraph(const osg::FrameStamp& frameStamp)
+{
+ DatabasePager::updateSceneGraph(frameStamp);
+}
+
+void ossimPlanetDatabasePager::compileGLObjects(osg::State& state,double& availableTime)
+{
+ DatabasePager::compileGLObjects(state, availableTime);
+}
+
+void ossimPlanetDatabasePager::compileAllGLObjects(osg::State& state)
+{
+ DatabasePager::compileAllGLObjects(state);
+}
+#endif
+#if 0
+#ifdef OSSIMPLANET_USE_PAGER
+
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <ossimPlanet/ossimPlanetPagedLandLod.h>
+#include <osg/Notify>
+#include <iostream>
+#include <osg/Texture>
+#include <osgDB/ReadFile>
+#include <algorithm>
+#include <osg/GraphicsThread>
+
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static int allocationCount = 0;
+#endif
+struct ossimPlanetDatabasePager::MyCompileOperation : public osg::GraphicsOperation
+{
+ MyCompileOperation(DatabasePager* databasePager);
+ virtual ~MyCompileOperation(){}
+ virtual void operator () (osg::GraphicsContext* context);
+
+ osg::observer_ptr<DatabasePager> _databasePager;
+};
+
+ossimPlanetDatabasePager::MyCompileOperation::MyCompileOperation(osgDB::DatabasePager* databasePager):
+ osg::GraphicsOperation("DatabasePager::MyCompileOperation",false),
+ _databasePager(databasePager)
+{
+}
+
+void ossimPlanetDatabasePager::MyCompileOperation::operator () (osg::GraphicsContext* context)
+{
+ // osg::notify(osg::NOTICE)<<"Background thread compiling"<<std::endl;
+ if (_databasePager.valid()) _databasePager->compileAllGLObjects(*(context->getState()));
+}
+
+struct ossimPlanetDatabasePager::MySortFileRequestFunctor
+{
+ bool operator() (const osg::ref_ptr<ossimPlanetDatabasePager::DatabaseRequest>& lhs,const osg::ref_ptr<ossimPlanetDatabasePager::DatabaseRequest>& rhs) const
+ {
+ if (lhs->_timestampLastRequest>rhs->_timestampLastRequest) return true;
+ else if (lhs->_timestampLastRequest<rhs->_timestampLastRequest) return false;
+ else return (lhs->_priorityLastRequest>rhs->_priorityLastRequest);
+ }
+};
+
+class ossimPlanetDatabasePager::MyFindCompileableGLObjectsVisitor : public osg::NodeVisitor
+{
+public:
+ MyFindCompileableGLObjectsVisitor(ossimPlanetDatabasePager::DataToCompile& dataToCompile,
+ bool changeAutoUnRef, bool valueAutoUnRef,
+ bool changeAnisotropy, float valueAnisotropy,
+ ossimPlanetDatabasePager::DrawablePolicy drawablePolicy):
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ _dataToCompile(dataToCompile),
+ _changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef),
+ _changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy),
+ _drawablePolicy(drawablePolicy)
+ {
+ }
+
+ virtual void apply(osg::Node& node)
+ {
+ apply(node.getStateSet());
+
+ traverse(node);
+ }
+
+ virtual void apply(osg::Geode& geode)
+ {
+ apply(geode.getStateSet());
+
+ for(unsigned int i=0;i<geode.getNumDrawables();++i)
+ {
+ apply(geode.getDrawable(i));
+ }
+
+ traverse(geode);
+ }
+
+ inline void apply(osg::StateSet* stateset)
+ {
+ if (stateset)
+ {
+ // search for the existance of any texture object attributes
+ bool foundTextureState = false;
+ for(unsigned int i=0;i<stateset->getTextureAttributeList().size();++i)
+ {
+ osg::Texture* texture = dynamic_cast<osg::Texture*>(stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
+ if (texture)
+ {
+ if (_changeAutoUnRef) texture->setUnRefImageDataAfterApply(_valueAutoUnRef);
+ if (_changeAnisotropy) texture->setMaxAnisotropy(_valueAnisotropy);
+ foundTextureState = true;
+ }
+ }
+
+ // if texture object attributes exist add the state to the list for later compilation.
+ if (foundTextureState)
+ {
+ //osg::notify(osg::DEBUG_INFO)<<"Found compilable texture state"<<std::endl;
+ _dataToCompile.first.insert(stateset);
+ }
+ }
+ }
+
+ inline void apply(osg::Drawable* drawable)
+ {
+ apply(drawable->getStateSet());
+
+ switch(_drawablePolicy)
+ {
+ case ossimPlanetDatabasePager::DO_NOT_MODIFY_DRAWABLE_SETTINGS:
+ // do nothing, leave settings as they came in from loaded database.
+ // osg::notify(osg::NOTICE)<<"DO_NOT_MODIFY_DRAWABLE_SETTINGS"<<std::endl;
+ break;
+ case ossimPlanetDatabasePager::USE_DISPLAY_LISTS:
+ drawable->setUseDisplayList(true);
+ drawable->setUseVertexBufferObjects(false);
+ break;
+ case ossimPlanetDatabasePager::USE_VERTEX_BUFFER_OBJECTS:
+ drawable->setUseDisplayList(true);
+ drawable->setUseVertexBufferObjects(true);
+ // osg::notify(osg::NOTICE)<<"USE_VERTEX_BUFFER_OBJECTS"<<std::endl;
+ break;
+ case ossimPlanetDatabasePager::USE_VERTEX_ARRAYS:
+ drawable->setUseDisplayList(false);
+ drawable->setUseVertexBufferObjects(false);
+ // osg::notify(osg::NOTICE)<<"USE_VERTEX_ARRAYS"<<std::endl;
+ break;
+ }
+
+ if (drawable->getUseDisplayList() || drawable->getUseVertexBufferObjects())
+ {
+ // osg::notify(osg::NOTICE)<<" Found compilable drawable"<<std::endl;
+ _dataToCompile.second.push_back(drawable);
+ }
+ }
+
+ ossimPlanetDatabasePager::DataToCompile& _dataToCompile;
+ bool _changeAutoUnRef;
+ bool _valueAutoUnRef;
+ bool _changeAnisotropy;
+ float _valueAnisotropy;
+ ossimPlanetDatabasePager::DrawablePolicy _drawablePolicy;
+};
+
+ossimPlanetDatabasePager::ossimPlanetDatabasePager()
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++allocationCount;
+ std::cout << "ossimPlanetDatabasePager Count: " << allocationCount << std::endl;
+#endif
+}
+ossimPlanetDatabasePager::~ossimPlanetDatabasePager()
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ --allocationCount;
+ std::cout << "ossimPlanetDatabasePager Count: " << allocationCount << std::endl;
+#endif
+}
+
+int ossimPlanetDatabasePager::cancel()
+{
+ return osgDB::DatabasePager::cancel();
+}
+
+void ossimPlanetDatabasePager::invalidateRequest(const std::string& requestString)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_fileRequestListMutex);
+ bool foundEntry = false;
+ for(DatabaseRequestList::iterator ritr = _fileRequestList.begin();
+ ritr != _fileRequestList.end() && !foundEntry;
+ ++ritr)
+ {
+ if ((*ritr)->_fileName==requestString)
+ {
+ (*ritr)->_frameNumberLastRequest = _frameNumber - 100000;
+ foundEntry = true;
+ }
+ }
+}
+
+void ossimPlanetDatabasePager::removeRequest(osg::Group* group)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_fileRequestListMutex);
+ for(DatabaseRequestList::iterator ritr = _fileRequestList.begin();
+ ritr != _fileRequestList.end();
+ ++ritr)
+ {
+ if ((*ritr)->_groupForAddingLoadedSubgraph==group)
+ {
+ _fileRequestList.erase(ritr);
+ break;
+ }
+ }
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_dataToCompileListMutex);
+ for(DatabaseRequestList::iterator ritr = _dataToCompileList.begin();
+ ritr != _dataToCompileList.end();
+ ++ritr)
+ {
+ if ((*ritr)->_groupForAddingLoadedSubgraph==group)
+ {
+ _dataToCompileList.erase(ritr);
+ break;
+ }
+ }
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_dataToMergeListMutex);
+ for(DatabaseRequestList::iterator ritr = _dataToMergeList.begin();
+ ritr != _dataToMergeList.end();
+ ++ritr)
+ {
+ if ((*ritr)->_groupForAddingLoadedSubgraph==group)
+ {
+ _dataToMergeList.erase(ritr);
+ break;
+ }
+ }
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_fileRequestListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(_dataToCompileListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock3(_dataToMergeListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock4(_childrenToDeleteListMutex);
+ updateDatabasePagerThreadBlock();
+ if(_dataToMergeList.empty()&&
+ _dataToCompileList.empty()&&
+ _fileRequestList.empty()&&
+ _childrenToDeleteList.empty())
+ {
+ notifyNoMoreWork();
+ }
+ }
+}
+
+void ossimPlanetDatabasePager::addToDeleteList(osg::Object* obj)
+{
+ if (_deleteRemovedSubgraphsInDatabaseThread)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_childrenToDeleteListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_fileRequestListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(_dataToCompileListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock3(_dataToMergeListMutex);
+ _childrenToDeleteList.push_back(obj);
+ notifyDoingWork();
+ updateDatabasePagerThreadBlock();
+ }
+}
+
+void ossimPlanetDatabasePager::requestNodeFile(const std::string& fileName,
+ osg::Group* group,
+ float priority,
+ const osg::FrameStamp* framestamp)
+{
+ DatabasePager::requestNodeFile(fileName,
+ group,
+ priority,
+ framestamp);
+ notifyDoingWork();
+}
+
+void ossimPlanetDatabasePager::run()
+{
+ osg::notify(osg::INFO)<<"DatabasePager::run()"<<std::endl;
+
+ // need to set the texture object manager to be able to reuse textures
+ osg::Texture::setMinimumNumberOfTextureObjectsToRetainInCache(100);
+
+ // need to set the texture object manager to be able to reuse textures
+ osg::Drawable::setMinimumNumberOfDisplayListsToRetainInCache(500);
+
+ bool firstTime = true;
+
+ do
+ {
+ _databasePagerThreadBlock->block();
+ //
+ // delete any children if required.
+ //
+// if (_deleteRemovedSubgraphsInDatabaseThread)
+ {
+ osg::ref_ptr<osg::Object> obj = 0;
+ {
+ int deleteCount = 0;
+ int deleteCountMax = 20;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_childrenToDeleteListMutex);
+ while (!_childrenToDeleteList.empty()&&(deleteCount < deleteCountMax))
+ {
+ //osg::notify(osg::NOTICE)<<"In DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" objects"<<std::endl;
+ //osg::Timer_t before = osg::Timer::instance()->tick();
+ obj = _childrenToDeleteList.back();
+ _childrenToDeleteList.pop_back();
+ //osg::notify(osg::NOTICE)<<"Done DatabasePager thread deleted in "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<" objects"<<std::endl;
+ ++deleteCount;
+ }
+ updateDatabasePagerThreadBlock();
+ }
+ }
+
+ //
+ // load any subgraphs that are required.
+ //
+ osg::ref_ptr<DatabaseRequest> databaseRequest;
+
+ // get the front of the file request list.
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_fileRequestListMutex);
+ if (!_fileRequestList.empty())
+ {
+ std::sort(_fileRequestList.begin(),_fileRequestList.end(),MySortFileRequestFunctor());
+ databaseRequest = _fileRequestList.front();
+ }
+ }
+
+ if (databaseRequest.valid())
+ {
+ // check if databaseRequest is still relevant
+ if (_frameNumber-databaseRequest->_frameNumberLastRequest<=1)
+ {
+
+ // assume that we only have one DatabasePager, or that readNodeFile is thread safe...
+ databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName,
+ databaseRequest->_loadOptions.get());
+
+ //osg::notify(osg::NOTICE)<<" node read in "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<std::endl;
+
+ bool loadedObjectsNeedToBeCompiled = false;
+
+ if (_doPreCompile && databaseRequest->_loadedModel.valid() && !_activeGraphicsContexts.empty())
+ {
+ // force a compute of the loaded model's bounding volume, so that when the subgraph
+ // merged with the main scene graph and large computeBound() isn't incurred.
+ databaseRequest->_loadedModel->getBound();
+
+
+ ActiveGraphicsContexts::iterator itr = _activeGraphicsContexts.begin();
+
+ DataToCompile& dtc = databaseRequest->_dataToCompileMap[*itr];
+ ++itr;
+
+ // find all the compileable rendering objects
+ MyFindCompileableGLObjectsVisitor frov(dtc,
+ _changeAutoUnRef, _valueAutoUnRef,
+ _changeAnisotropy, _valueAnisotropy,
+ _drawablePolicy);
+
+ databaseRequest->_loadedModel->accept(frov);
+
+ if (!dtc.first.empty() || !dtc.second.empty())
+ {
+ loadedObjectsNeedToBeCompiled = true;
+
+ // copy the objects from the compile list to the other graphics context list.
+ for(;
+ itr != _activeGraphicsContexts.end();
+ ++itr)
+ {
+ databaseRequest->_dataToCompileMap[*itr] = dtc;
+ }
+ }
+ }
+
+ // move the databaseRequest from the front of the fileRequest to the end of
+ // dataToCompile or dataToMerge lists.
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_fileRequestListMutex);
+
+ DatabaseRequestList::iterator itr = std::find(_fileRequestList.begin(),_fileRequestList.end(),databaseRequest);
+ if (itr != _fileRequestList.end())
+ {
+ if (databaseRequest->_loadedModel.valid())
+ {
+ if (loadedObjectsNeedToBeCompiled)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_dataToCompileListMutex);
+ _dataToCompileList.push_back(databaseRequest);
+ notifyUpdateSceneGraph();
+ }
+ else
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_dataToMergeListMutex);
+ _dataToMergeList.push_back(databaseRequest);
+ notifyUpdateSceneGraph();
+ }
+ }
+ _fileRequestList.erase(itr);
+ }
+
+ updateDatabasePagerThreadBlock();
+ }
+
+ if (loadedObjectsNeedToBeCompiled)
+ {
+ for(ActiveGraphicsContexts::iterator itr = _activeGraphicsContexts.begin();
+ itr != _activeGraphicsContexts.end();
+ ++itr)
+ {
+ osg::GraphicsContext* gc = osg::GraphicsContext::getCompileContext(*itr);
+ if (gc)
+ {
+ osg::GraphicsThread* gt = gc->getGraphicsThread();
+ if (gt)
+ {
+ gt->add(new ossimPlanetDatabasePager::MyCompileOperation(this));
+ }
+ else
+ {
+ gc->makeCurrent();
+
+ compileAllGLObjects(*(gc->getState()));
+
+ gc->releaseContext();
+ }
+ }
+ }
+
+ // osg::notify(osg::NOTICE)<<"Done compiling in paging thread"<<std::endl;
+ }
+
+ }
+ else
+ {
+ //std::cout<<"frame number delta for "<<databaseRequest->_fileName<<" "<<_frameNumber-databaseRequest->_frameNumberLastRequest<<std::endl;
+ // remove the databaseRequest from the front of the fileRequest to the end of
+ // dataLoad list as its is no longer relevant
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_fileRequestListMutex);
+
+ if (!_fileRequestList.empty()) _fileRequestList.erase(_fileRequestList.begin());
+
+ updateDatabasePagerThreadBlock();
+
+ }
+ }
+ else
+ {
+ }
+ // go to sleep till our the next time our thread gets scheduled.
+
+ if (firstTime)
+ {
+ // do a yield to get round a peculiar thread hang when testCancel() is called
+ // in certain cirumstances - of which there is no particular pattern.
+ YieldCurrentThread();
+ firstTime = false;
+ }
+
+ } while (!testCancel() && !_done);
+}
+
+void ossimPlanetDatabasePager::clearRequests()
+{
+ DatabasePager::clear();
+}
+
+void ossimPlanetDatabasePager::updateSceneGraph(double currentFrameTime)
+{
+ osgDB::DatabasePager::updateSceneGraph(currentFrameTime);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_fileRequestListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(_dataToCompileListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock3(_dataToMergeListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock4(_childrenToDeleteListMutex);
+ if(_dataToMergeList.empty()&&
+ _dataToCompileList.empty()&&
+ _fileRequestList.empty()&&
+ _childrenToDeleteList.empty())
+ {
+ notifyNoMoreWork();
+ }
+ updateDatabasePagerThreadBlock();
+}
+
+bool ossimPlanetDatabasePager::listsAreEmpty()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_fileRequestListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(_dataToCompileListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock3(_dataToMergeListMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock4(_childrenToDeleteListMutex);
+
+ return (_dataToMergeList.empty()&&
+ _dataToCompileList.empty()&&
+ _fileRequestList.empty()&&
+ _childrenToDeleteList.empty());
+}
+
+void ossimPlanetDatabasePager::addCallback(osg::ref_ptr<ossimPlanetDatabasePager::Callback> callback)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ ossimPlanetDatabasePager::CallbackListType::iterator i = std::find(theCallbackList.begin(),
+ theCallbackList.end(),
+ callback);
+ if(i == theCallbackList.end())
+ {
+ theCallbackList.push_back(callback);
+ }
+}
+
+void ossimPlanetDatabasePager::removeCallback(osg::ref_ptr<ossimPlanetDatabasePager::Callback> callback)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ ossimPlanetDatabasePager::CallbackListType::iterator i = std::find(theCallbackList.begin(),
+ theCallbackList.end(),
+ callback);
+ if(i != theCallbackList.end())
+ {
+ theCallbackList.erase(i);
+ }
+}
+
+void ossimPlanetDatabasePager::notifyDoingWork()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ theCallbackList[idx]->doingWork();
+ }
+}
+
+void ossimPlanetDatabasePager::notifyNoMoreWork()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ theCallbackList[idx]->noMoreWork();
+ }
+}
+
+void ossimPlanetDatabasePager::notifyUpdateSceneGraph()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theCallbackList.size(); ++idx)
+ {
+ theCallbackList[idx]->updateSceneGraph();
+ }
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetDepthPartitionNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetDepthPartitionNode.cpp
new file mode 100644
index 0000000..2b70875
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetDepthPartitionNode.cpp
@@ -0,0 +1,272 @@
+/* OpenSceneGraph example, osgdepthpartion.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#include <ossimPlanet/ossimPlanetDepthPartitionNode.h>
+#include <osgUtil/CullVisitor>
+
+using namespace osg;
+
+#define CURRENT_CLASS ossimPlanetDepthPartitionNode
+
+CURRENT_CLASS::CURRENT_CLASS()
+{
+ _distAccumulator = new ossimPlanetDistanceAccumulator;
+ init();
+}
+
+CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop)
+ : osg::Group(dpn, copyop),
+ _active(dpn._active),
+ _renderOrder(dpn._renderOrder),
+ _clearColorBuffer(dpn._clearColorBuffer)
+{
+ _distAccumulator = new ossimPlanetDistanceAccumulator;
+ _numCameras = 0;
+}
+
+CURRENT_CLASS::~CURRENT_CLASS() {}
+
+void CURRENT_CLASS::init()
+{
+ _active = true;
+ _numCameras = 0;
+ setCullingActive(false);
+ _renderOrder = osg::Camera::POST_RENDER;
+ _clearColorBuffer = true;
+}
+
+void CURRENT_CLASS::setActive(bool active)
+{
+ if(_active == active) return;
+ _active = active;
+}
+
+void CURRENT_CLASS::setClearColorBuffer(bool clear)
+{
+ _clearColorBuffer = clear;
+
+ // Update the render order for the first Camera if it exists
+ if(!_cameraList.empty())
+ {
+ if(clear)
+ _cameraList[0]->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ else
+ _cameraList[0]->setClearMask(GL_DEPTH_BUFFER_BIT);
+ }
+}
+
+void CURRENT_CLASS::setRenderOrder(osg::Camera::RenderOrder order)
+{
+ _renderOrder = order;
+
+ // Update the render order for existing Cameras
+ unsigned int numCameras = _cameraList.size();
+ for(unsigned int i = 0; i < numCameras; i++)
+ {
+ _cameraList[i]->setRenderOrder(_renderOrder);
+ }
+}
+
+void CURRENT_CLASS::traverse(osg::NodeVisitor &nv)
+{
+ // If the scene hasn't been defined then don't do anything
+ unsigned int numChildren = _children.size();
+ if(numChildren == 0) return;
+
+ // If the node is not active then don't analyze it
+ if(!_active)
+ {
+ // Traverse the graph as usual
+ Group::traverse(nv);
+ return;
+ }
+
+ // If the visitor is not a cull visitor, pass it directly onto the scene.
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(!cv)
+ {
+ Group::traverse(nv);
+ return;
+ }
+
+ // We are in the cull traversal, so first collect information on the
+ // current modelview and projection matrices and viewport.
+ osg::RefMatrix& modelview = *(cv->getModelViewMatrix());
+ osg::RefMatrix& projection = *(cv->getProjectionMatrix());
+ osg::Viewport* viewport = cv->getViewport();
+
+ // Prepare for scene traversal.
+ _distAccumulator->setMatrices(modelview, projection);
+ _distAccumulator->setNearFarRatio(cv->getNearFarRatio());
+ _distAccumulator->reset();
+
+ // Step 1: Traverse the children, collecting the near/far distances.
+ unsigned int i;
+ for(i = 0; i < numChildren; i++)
+ {
+ _children[i]->accept(*(_distAccumulator.get()));
+ }
+
+ // Step 2: Compute the near and far distances for every Camera that
+ // should be used to render the scene.
+ _distAccumulator->computeCameraPairs();
+
+ // Step 3: Create the Cameras, and add them as children.
+ ossimPlanetDistanceAccumulator::PairList& camPairs = _distAccumulator->getCameraPairs();
+ _numCameras = camPairs.size(); // Get the number of cameras
+
+ // Create the Cameras, and add them as children.
+ if(_numCameras > 0)
+ {
+ osg::Camera *currCam;
+ ossimPlanetDistanceAccumulator::DistancePair currPair;
+
+ for(i = 0; i < _numCameras; i++)
+ {
+ // Create the camera, and clamp it's projection matrix
+ currPair = camPairs[i]; // (near,far) pair for current camera
+ currCam = createOrReuseCamera(projection, currPair.first,
+ currPair.second, i);
+
+ // Set the modelview matrix and viewport of the camera
+ currCam->setViewMatrix(modelview);
+ currCam->setViewport(viewport);
+
+ // Redirect the CullVisitor to the current camera
+ currCam->accept(nv);
+ }
+
+ // Set the clear color for the first camera
+ _cameraList[0]->setClearColor(cv->getRenderStage()->getClearColor());
+ }
+}
+
+bool CURRENT_CLASS::addChild(osg::Node *child)
+{
+ return insertChild(_children.size(), child);
+}
+
+bool CURRENT_CLASS::insertChild(unsigned int index, osg::Node *child)
+{
+ if(!Group::insertChild(index, child)) return false; // Insert child
+
+ // Insert child into each Camera
+ unsigned int totalCameras = _cameraList.size();
+ for(unsigned int i = 0; i < totalCameras; i++)
+ {
+ _cameraList[i]->insertChild(index, child);
+ }
+ return true;
+}
+
+
+bool CURRENT_CLASS::removeChildren(unsigned int pos, unsigned int numRemove)
+{
+ if(!Group::removeChildren(pos, numRemove)) return false; // Remove child
+
+ // Remove child from each Camera
+ unsigned int totalCameras = _cameraList.size();
+ for(unsigned int i = 0; i < totalCameras; i++)
+ {
+ _cameraList[i]->removeChildren(pos, numRemove);
+ }
+ return true;
+}
+
+bool CURRENT_CLASS::setChild(unsigned int i, osg::Node *node)
+{
+ if(!Group::setChild(i, node)) return false; // Set child
+
+ // Set child for each Camera
+ unsigned int totalCameras = _cameraList.size();
+ for(unsigned int j = 0; j < totalCameras; j++)
+ {
+ _cameraList[j]->setChild(i, node);
+ }
+ return true;
+}
+
+osg::Camera* CURRENT_CLASS::createOrReuseCamera(const osg::Matrix& proj,
+ double znear, double zfar,
+ const unsigned int &camNum)
+{
+ if(_cameraList.size() <= camNum) _cameraList.resize(camNum+1);
+ osg::Camera *camera = _cameraList[camNum].get();
+
+ if(!camera) // Create a new Camera
+ {
+ camera = new osg::Camera;
+ camera->setCullingActive(false);
+ camera->setRenderOrder(_renderOrder);
+ camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+
+ // We will compute the near/far planes ourselves
+ camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING);
+
+ if(camNum == 0 && _clearColorBuffer)
+ camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ else
+ camera->setClearMask(GL_DEPTH_BUFFER_BIT);
+
+ // Add our children to the new Camera's children
+ unsigned int numChildren = _children.size();
+ for(unsigned int i = 0; i < numChildren; i++)
+ {
+ camera->addChild(_children[i].get());
+ }
+
+ _cameraList[camNum] = camera;
+ }
+
+ osg::Matrixd &projection = camera->getProjectionMatrix();
+ projection = proj;
+
+ // Slightly inflate the near & far planes to avoid objects at the
+ // extremes being clipped out.
+ znear *= 0.999;
+ zfar *= 1.001;
+
+ // Clamp the projection matrix z values to the range (near, far)
+ double epsilon = 1.0e-6;
+ if(fabs(projection(0,3)) < epsilon &&
+ fabs(projection(1,3)) < epsilon &&
+ fabs(projection(2,3)) < epsilon ) // Projection is Orthographic
+ {
+ epsilon = -1.0/(zfar - znear); // Used as a temp variable
+ projection(2,2) = 2.0*epsilon;
+ projection(3,2) = (zfar + znear)*epsilon;
+ }
+ else // Projection is Perspective
+ {
+ double trans_near = (-znear*projection(2,2) + projection(3,2)) /
+ (-znear*projection(2,3) + projection(3,3));
+ double trans_far = (-zfar*projection(2,2) + projection(3,2)) /
+ (-zfar*projection(2,3) + projection(3,3));
+ double ratio = fabs(2.0/(trans_near - trans_far));
+ double center = -0.5*(trans_near + trans_far);
+
+ projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, ratio, 0.0,
+ 0.0, 0.0, center*ratio, 1.0));
+ }
+
+ return camera;
+}
+#undef CURRENT_CLASS
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetDestinationCommandAction.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetDestinationCommandAction.cpp
new file mode 100644
index 0000000..81530bd
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetDestinationCommandAction.cpp
@@ -0,0 +1,97 @@
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+#include <ossim/base/ossimCommon.h>
+
+const char ossimPlanetDestinationCommandAction::theWhitespace[] = " \t";
+
+ossimPlanetDestinationCommandAction::ossimPlanetDestinationCommandAction(const ossimString& code,
+ const ossimString& originatingFederate)
+:ossimPlanetAction(originatingFederate)
+{
+ setSourceCode(code);
+}
+
+ossimString ossimPlanetDestinationCommandAction::argListSource() const
+{
+ int start = -1;
+
+ if (theCommand != "#")
+ {
+ start = theSourceCode.find_first_not_of(theWhitespace, 0); // eat leading whitespace
+ int end = theSourceCode.find_first_of(theWhitespace, start);
+ start = theSourceCode.find_first_not_of(theWhitespace, end); // eat target
+ end = theSourceCode.find_first_of(theWhitespace, start);
+ start = theSourceCode.find_first_not_of(theWhitespace, end); // eat command
+
+ }
+ return (start > 0) ? ossimString(theSourceCode.substr(start, theSourceCode.length() - start)) :
+ ossimString();
+}
+
+bool ossimPlanetDestinationCommandAction::setSourceCode(const ossimString& newSourcecode)
+{
+ bool result = true;
+ theSourceCode = newSourcecode;
+
+ int start = theSourceCode.find_first_not_of(theWhitespace, 0);
+ bool isComment = start < 0 || theSourceCode[(size_t)start] == '#';
+
+ if (isComment)
+ {
+ theTokens.clear();
+ theTokens.push_back(":");
+ theTokens.push_back("#");
+ }
+ else
+ {
+ bool unbalancedBraces;
+ ossim::lexQuotedTokens(theSourceCode, start, theWhitespace, "{}", theTokens, unbalancedBraces);
+ if (unbalancedBraces || theTokens.size() == 1)
+ {
+ theTokens.clear();
+ theTokens.push_back(":");
+ theTokens.push_back("#syntaxerror");
+ result = false;
+ }
+ }
+ theArgCount = 0;
+ if(theTokens.size() > 2)
+ {
+ theArgCount = theTokens.size()-2;
+ }
+
+ setTarget(theTokens[0]);
+ setCommand(theTokens[1]);
+
+ return result;
+}
+
+void ossimPlanetDestinationCommandAction::print(std::ostream& s)const
+{
+ const char* pre[] = {"", "{"};
+ const char* postToken[] = {" ", "", "} ", "}" };
+ ossim_uint32 i;
+ for (i = 0; i < theTokens.size(); i++)
+ {
+ ossim_int32 needsQuoting = theTokens[i].empty() || (int)theTokens[i].find_first_of(theWhitespace, 0) != -1;
+ ossim_int32 lastToken = i == theTokens.size() - 1;
+ s << pre[needsQuoting] << theTokens[i] << postToken[2*needsQuoting + lastToken];
+ }
+}
+
+void ossimPlanetDestinationCommandAction::read(std::istream& s)
+{
+ ossimString buffer;
+ buffer.reserve(1000);
+
+ // read arbitrary length line from s into buffer.
+ char c;
+ for (s.get(c); s.gcount() == 1 && c != '\n' && !s.eof(); s.get(c))
+ buffer.append(1, c);
+
+ // init the ossimPlanetAction
+ if (s || s.eof())
+ {
+ setSourceCode(buffer);
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetDistanceAccumulator.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetDistanceAccumulator.cpp
new file mode 100644
index 0000000..432a9bb
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetDistanceAccumulator.cpp
@@ -0,0 +1,402 @@
+/* OpenSceneGraph example, osgdepthpartion.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#include <ossimPlanet/ossimPlanetDistanceAccumulator.h>
+#include <osg/Geode>
+#include <osg/Transform>
+#include <osg/Projection>
+#include <algorithm>
+#include <math.h>
+#include <limits.h>
+
+/** Function that sees whether one DistancePair should come before another in
+ an sorted list. Used to sort the vector of DistancePairs. */
+static bool precedes(const ossimPlanetDistanceAccumulator::DistancePair &a,
+ const ossimPlanetDistanceAccumulator::DistancePair &b)
+{
+ // This results in sorting in order of descending far distances
+ if(a.second > b.second) return true;
+ else return false;
+}
+
+/** Computes distance (in z direction) betwen a point and the viewer's eye,
+ given by a view matrix */
+static double distance(const osg::Vec3 &coord, const osg::Matrix& matrix)
+{
+ // Here we are taking only the z coordinate of the point transformed
+ // by the matrix, ie coord*matrix. The negative sign is because we
+ // want to consider into the screen as INCREASING distance.
+ return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) +
+ coord[2]*matrix(2,2) + matrix(3,2) );
+}
+
+#define CURRENT_CLASS ossimPlanetDistanceAccumulator
+CURRENT_CLASS::CURRENT_CLASS()
+ : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
+ _nearFarRatio(0.0005), _maxDepth(UINT_MAX)
+{
+ setMatrices(osg::Matrix::identity(), osg::Matrix::identity());
+ reset();
+}
+
+CURRENT_CLASS::~CURRENT_CLASS() {}
+
+void CURRENT_CLASS::pushLocalFrustum()
+{
+ osg::Matrix& currMatrix = _viewMatrices.back();
+
+ // Compute the frustum in local space
+ osg::Polytope localFrustum;
+ localFrustum.setToUnitFrustum(false, false);
+ localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
+ _localFrusta.push_back(localFrustum);
+
+ // Compute new bounding box corners
+ bbCornerPair corner;
+ corner.second = (currMatrix(0,2)<=0?1:0) |
+ (currMatrix(1,2)<=0?2:0) |
+ (currMatrix(2,2)<=0?4:0);
+ corner.first = (~corner.second)&7;
+ _bbCorners.push_back(corner);
+}
+
+void CURRENT_CLASS::pushDistancePair(double zNear, double zFar)
+{
+ if(zFar > 0.0) // Make sure some of drawable is visible
+ {
+ // Make sure near plane is in front of viewpoint.
+ if(zNear <= 0.0)
+ {
+ zNear = zFar*_nearFarRatio;
+ if(zNear >= 1.0) zNear = 1.0; // 1.0 limit chosen arbitrarily!
+ }
+
+ // Add distance pair for current drawable
+ _distancePairs.push_back(DistancePair(zNear, zFar));
+
+ // Override the current nearest/farthest planes if necessary
+ if(zNear < _limits.first) _limits.first = zNear;
+ if(zFar > _limits.second) _limits.second = zFar;
+ }
+}
+
+/** Return true if the node should be traversed, and false if the bounding sphere
+ of the node is small enough to be rendered by one Camera. If the latter
+ is true, then store the node's near & far plane distances. */
+bool CURRENT_CLASS::shouldContinueTraversal(osg::Node &node)
+{
+ // Allow traversal to continue if we haven't reached maximum depth.
+ bool keepTraversing = (_currentDepth < _maxDepth);
+
+ osg::BoundingSphere bs = node.getBound();
+ double zNear = 0.0, zFar = 0.0;
+
+ // Make sure bounding sphere is valid
+ if(bs.valid())
+ {
+ // Make sure bounding sphere is within the viewing volume
+ if(!_localFrusta.back().contains(bs)) keepTraversing = false;
+
+ else // Compute near and far planes for this node
+ {
+ // Since the view matrix could involve complex transformations,
+ // we need to determine a new BoundingSphere that would encompass
+ // the transformed BoundingSphere.
+ const osg::Matrix &l2w = _viewMatrices.back();
+
+ // Get the transformed x-axis of the BoundingSphere
+ osg::Vec3d newX = bs._center;
+ newX.x() += bs._radius; // Get X-edge of bounding sphere
+ newX = newX * l2w;
+
+ // Get the transformed y-axis of the BoundingSphere
+ osg::Vec3d newY = bs._center;
+ newY.y() += bs._radius; // Get Y-edge of bounding sphere
+ newY = newY * l2w;
+
+ // Get the transformed z-axis of the BoundingSphere
+ osg::Vec3d newZ = bs._center;
+ newZ.z() += bs._radius; // Get Z-edge of bounding sphere
+ newZ = newZ * l2w;
+
+ // Get the transformed center of the BoundingSphere
+ bs._center = bs._center * l2w;
+
+ // Compute lengths of transformed x, y, and z axes
+ double newXLen = (newX - bs._center).length();
+ double newYLen = (newY - bs._center).length();
+ double newZLen = (newZ - bs._center).length();
+
+ // The encompassing radius is the max of the transformed lengths
+ bs._radius = newXLen;
+ if(newYLen > bs._radius) bs._radius = newYLen;
+ if(newZLen > bs._radius) bs._radius = newZLen;
+
+ // Now we can compute the near & far planes, noting that for
+ // complex view transformations (ie. involving scales) the new
+ // BoundingSphere may be bigger than the original one.
+ // Note that the negative sign on the bounding sphere center is
+ // because we want distance to increase INTO the screen.
+ zNear = -bs._center.z() - bs._radius;
+ zFar = -bs._center.z() + bs._radius;
+
+ // If near/far ratio is big enough, then we don't need to keep
+ // traversing children of this node.
+ if(zNear >= zFar*_nearFarRatio) keepTraversing = false;
+ }
+ }
+
+ // If traversal should stop, then store this node's (near,far) pair
+ if(!keepTraversing) pushDistancePair(zNear, zFar);
+
+ return keepTraversing;
+}
+
+void CURRENT_CLASS::apply(osg::Node &node)
+{
+ if(shouldContinueTraversal(node))
+ {
+ // Traverse this node
+ ++_currentDepth;
+ traverse(node);
+ --_currentDepth;
+ }
+}
+
+void CURRENT_CLASS::apply(osg::Projection &proj)
+{
+ if(shouldContinueTraversal(proj))
+ {
+ // Push the new projection matrix view frustum
+ _projectionMatrices.push_back(proj.getMatrix());
+ pushLocalFrustum();
+
+ // Traverse the group
+ ++_currentDepth;
+ traverse(proj);
+ --_currentDepth;
+
+ // Reload original matrix and frustum
+ _localFrusta.pop_back();
+ _bbCorners.pop_back();
+ _projectionMatrices.pop_back();
+ }
+}
+
+void CURRENT_CLASS::apply(osg::Transform &transform)
+{
+ if(shouldContinueTraversal(transform))
+ {
+ // Compute transform for current node
+ osg::Matrix currMatrix = _viewMatrices.back();
+ bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
+
+ if(pushMatrix)
+ {
+ // Store the new modelview matrix and view frustum
+ _viewMatrices.push_back(currMatrix);
+ pushLocalFrustum();
+ }
+
+ ++_currentDepth;
+ traverse(transform);
+ --_currentDepth;
+
+ if(pushMatrix)
+ {
+ // Restore the old modelview matrix and view frustum
+ _localFrusta.pop_back();
+ _bbCorners.pop_back();
+ _viewMatrices.pop_back();
+ }
+ }
+}
+
+void CURRENT_CLASS::apply(osg::Geode &geode)
+{
+ // Contained drawables will only be individually considered if we are
+ // allowed to continue traversing.
+ if(shouldContinueTraversal(geode))
+ {
+ osg::Drawable *drawable;
+ double zNear, zFar;
+
+ // Handle each drawable in this geode
+ for(unsigned int i = 0; i < geode.getNumDrawables(); ++i)
+ {
+ drawable = geode.getDrawable(i);
+
+ const osg::BoundingBox &bb = drawable->getBound();
+ if(bb.valid())
+ {
+ // Make sure drawable will be visible in the scene
+ if(!_localFrusta.back().contains(bb)) continue;
+
+ // Compute near/far distances for current drawable
+ zNear = distance(bb.corner(_bbCorners.back().first),
+ _viewMatrices.back());
+ zFar = distance(bb.corner(_bbCorners.back().second),
+ _viewMatrices.back());
+ if(zNear > zFar) std::swap(zNear, zFar);
+ pushDistancePair(zNear, zFar);
+ }
+ }
+ }
+}
+
+void CURRENT_CLASS::setMatrices(const osg::Matrix &modelview,
+ const osg::Matrix &projection)
+{
+ _modelview = modelview;
+ _projection = projection;
+}
+
+void CURRENT_CLASS::reset()
+{
+ // Clear vectors & values
+ _distancePairs.clear();
+ _cameraPairs.clear();
+ _limits.first = DBL_MAX;
+ _limits.second = 0.0;
+ _currentDepth = 0;
+
+ // Initial transform matrix is the modelview matrix
+ _viewMatrices.clear();
+ _viewMatrices.push_back(_modelview);
+
+ // Set the initial projection matrix
+ _projectionMatrices.clear();
+ _projectionMatrices.push_back(_projection);
+
+ // Create a frustum without near/far planes, for cull computations
+ _localFrusta.clear();
+ _bbCorners.clear();
+ pushLocalFrustum();
+}
+
+void CURRENT_CLASS::computeCameraPairs()
+{
+ // Nothing in the scene, so no cameras needed
+ if(_distancePairs.empty()) return;
+
+ // Entire scene can be handled by just one camera
+ if(_limits.first >= _limits.second*_nearFarRatio)
+ {
+ _cameraPairs.push_back(_limits);
+ return;
+ }
+
+ PairList::iterator i,j;
+
+ // Sort the list of distance pairs by descending far distance
+ std::sort(_distancePairs.begin(), _distancePairs.end(), precedes);
+
+ // Combine overlapping distance pairs. The resulting set of distance
+ // pairs (called combined pairs) will not overlap.
+ PairList combinedPairs;
+ DistancePair currPair = _distancePairs.front();
+ for(i = _distancePairs.begin(); i != _distancePairs.end(); ++i)
+ {
+ // Current distance pair does not overlap current combined pair, so
+ // save the current combined pair and start a new one.
+ if(i->second < 0.99*currPair.first)
+ {
+ combinedPairs.push_back(currPair);
+ currPair = *i;
+ }
+
+ // Current distance pair overlaps current combined pair, so expand
+ // current combined pair to encompass distance pair.
+ else
+ currPair.first = std::min(i->first, currPair.first);
+ }
+ combinedPairs.push_back(currPair); // Add last pair
+
+ // Compute the (near,far) distance pairs for each camera.
+ // Each of these distance pairs is called a "view segment".
+ double currNearLimit, numSegs, new_ratio;
+ double ratio_invlog = 1.0/log(_nearFarRatio);
+ unsigned int temp;
+ for(i = combinedPairs.begin(); i != combinedPairs.end(); ++i)
+ {
+ currPair = *i; // Save current view segment
+
+ // Compute the fractional number of view segments needed to span
+ // the current combined distance pair.
+ currNearLimit = currPair.second*_nearFarRatio;
+ if(currPair.first >= currNearLimit) numSegs = 1.0;
+ else
+ {
+ numSegs = log(currPair.first/currPair.second)*ratio_invlog;
+
+ // Compute the near plane of the last view segment
+ //currNearLimit *= pow(_nearFarRatio, -floor(-numSegs) - 1);
+ for(temp = (unsigned int)(-floor(-numSegs)); temp > 1; temp--)
+ {
+ currNearLimit *= _nearFarRatio;
+ }
+ }
+
+ // See if the closest view segment can absorb other combined pairs
+ for(j = i+1; j != combinedPairs.end(); ++j)
+ {
+ // No other distance pairs can be included
+ if(j->first < currNearLimit) break;
+ }
+
+ // If we did absorb another combined distance pair, recompute the
+ // number of required view segments.
+ if(i != j-1)
+ {
+ i = j-1;
+ currPair.first = i->first;
+ if(currPair.first >= currPair.second*_nearFarRatio) numSegs = 1.0;
+ else numSegs = log(currPair.first/currPair.second)*ratio_invlog;
+ }
+
+ /* Compute an integer number of segments by rounding the fractional
+ number of segments according to how many segments there are.
+ In general, the more segments there are, the more likely that the
+ integer number of segments will be rounded down.
+ The purpose of this is to try to minimize the number of view segments
+ that are used to render any section of the scene without violating
+ the specified _nearFarRatio by too much. */
+ if(numSegs < 10.0) numSegs = floor(numSegs + 1.0 - 0.1*floor(numSegs));
+ else numSegs = floor(numSegs);
+
+
+ // Compute the near/far ratio that will be used for each view segment
+ // in this section of the scene.
+ new_ratio = pow(currPair.first/currPair.second, 1.0/numSegs);
+
+ // Add numSegs new view segments to the camera pairs list
+ for(temp = (unsigned int)numSegs; temp > 0; temp--)
+ {
+ currPair.first = currPair.second*new_ratio;
+ _cameraPairs.push_back(currPair);
+ currPair.second = currPair.first;
+ }
+ }
+}
+
+void CURRENT_CLASS::setNearFarRatio(double ratio)
+{
+ if(ratio <= 0.0 || ratio >= 1.0) return;
+ _nearFarRatio = ratio;
+}
+#undef CURRENT_CLASS
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetDtedElevationDatabase.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetDtedElevationDatabase.cpp
new file mode 100644
index 0000000..93d6b5a
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetDtedElevationDatabase.cpp
@@ -0,0 +1,715 @@
+#include <ossimPlanet/ossimPlanetDtedElevationDatabase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimRegExp.h>
+#include <ossim/support_data/ossimDtedVol.h>
+#include <ossim/support_data/ossimDtedHdr.h>
+#include <ossim/support_data/ossimDtedUhl.h>
+#include <ossim/support_data/ossimDtedDsi.h>
+#include <ossim/support_data/ossimDtedAcc.h>
+#include <ossim/support_data/ossimDtedRecord.h>
+#include <sstream>
+
+ossimPlanetDtedElevationDatabase::ossimPlanetDtedElevationDatabase()
+ :ossimPlanetElevationDatabase()
+{
+ theOpenFlag = false;
+ theLocation = "";
+ theMaxOpenFiles = 25;
+ theMinOpenFiles = 20;
+
+ theSwapBytesFlag = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN;
+}
+
+ossimPlanetDtedElevationDatabase::ossimPlanetDtedElevationDatabase(const ossimPlanetDtedElevationDatabase& src)
+ :ossimPlanetElevationDatabase(src),
+ theLocation(src.theLocation),
+ theOpenFlag(src.theOpenFlag),
+ theMaxOpenFiles(src.theMaxOpenFiles),
+ theMinOpenFiles(src.theMinOpenFiles)
+{
+ theSwapBytesFlag = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN;
+}
+
+ossimPlanetDtedElevationDatabase::~ossimPlanetDtedElevationDatabase()
+{
+}
+
+ossimPlanetTextureLayer* ossimPlanetDtedElevationDatabase::dup()const
+{
+ return new ossimPlanetDtedElevationDatabase(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetDtedElevationDatabase::dupType()const
+{
+ return new ossimPlanetDtedElevationDatabase;
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetDtedElevationDatabase::updateExtents()
+{
+
+ theDirtyExtentsFlag = false;
+ return theStateCode;
+}
+
+void ossimPlanetDtedElevationDatabase::updateStats()const
+{
+ theStats->setTotalTextureSize(0);
+ theDirtyStatsFlag = false;
+
+}
+
+void ossimPlanetDtedElevationDatabase::resetStats()const
+{
+ theStats->setBytesTransferred(0);
+ theStats->setTotalTextureSize(0);
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetDtedElevationDatabase::open(const std::string& location)
+{
+ ossimElevManager::ConnectionStringVisitor visitor(location);
+
+ ossimElevManager::instance()->accept(visitor);
+ //std::cout << "DATABASE ==== " << (visitor.getElevationDatabase()?visitor.getElevationDatabase()->getConnectionString():"NOT FOUND") << std::endl;
+
+ ossimFilename file(location);
+ bool result = false;
+ theLocation = "";
+ theExtents = new ossimPlanetExtents;
+ ossim_uint32 count = 0;
+ ossim_uint32 maxCount = 25;
+ if(file.exists())
+ {
+ if(file.isDir())
+ {
+ ossimDirectory dir;
+
+ if(dir.open(file))
+ {
+ ossimFilename testFile;
+ if(dir.getFirst(testFile))
+ {
+ ++count;
+ do
+ {
+ ossimRegExp eastern;
+ ossimRegExp western;
+ ossimRegExp easternUp;
+ ossimRegExp westernUp;
+ eastern.compile("e[0-9][0-9][0-9]");
+ western.compile("w[0-9][0-9][0-9]");
+ easternUp.compile("E[0-9][0-9][0-9]");
+ westernUp.compile("W[0-9][0-9][0-9]");
+ if(testFile.isDir())
+ {
+ if(eastern.find(testFile.c_str())||
+ western.find(testFile.c_str())||
+ easternUp.find(testFile.c_str())||
+ westernUp.find(testFile.c_str()))
+ {
+ result = true;
+ }
+ if(result)
+ {
+ result = false; // now find a North South file
+ ossimDirectory dirNS;
+ dirNS.open(testFile);
+ if(dirNS.getFirst(testFile))
+ {
+ do
+ {
+ std::ifstream in;
+
+ in.open(testFile.c_str(), std::ios::binary|std::ios::in);
+
+ if(!in.fail())
+ {
+
+ ossimDtedVol vol(in);
+ ossimDtedHdr hdr(in);
+ ossimDtedUhl uhl(in);
+ ossimDtedDsi dsi(in);
+ ossimDtedAcc acc(in);
+
+ if(uhl.getErrorStatus() != ossimErrorCodes::OSSIM_ERROR)
+ {
+ double metersPerPixel = ossimGpt().metersPerDegree().y*uhl.latInterval();
+ dirtyExtents(); // make sure parents are marked as dirty
+
+ if(fabs(metersPerPixel - (ossimGpt().metersPerDegree().y *(30.0/3600))) < .25) // 30 arc
+ {
+ setName("DTED0");
+ setDescription("DTED 1 kilometer elevation database");
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 6));
+ }
+ else if(fabs(metersPerPixel - (ossimGpt().metersPerDegree().y *(3.0/3600))) < .25) // 3 arc
+ {
+ setName("DTED1");
+ setDescription("DTED 90 meter elevation database");
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 8));
+ }
+ else if(fabs(metersPerPixel - (ossimGpt().metersPerDegree().y *(1.0/3600))) < .25) // 1 arc
+ {
+ setName("DTED2");
+ setDescription("DTED 30 meter elevation database");
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 10));
+ }
+ else
+ {
+ setName("DTED");
+ setDescription("DTED elevation database");
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 12));
+ }
+ result = true;
+ }
+ }
+ }while(dirNS.getNext(testFile)&&(!result));
+ }
+ }
+ }
+
+ }while(dir.getNext(testFile)&&(!result)&&(count < maxCount));
+ }
+ }
+ }
+ }
+
+ theOpenFlag = result;
+ if(theOpenFlag)
+ {
+ theStateCode = ossimPlanetTextureLayer_VALID;
+ theLocation = location;
+ }
+ else
+ {
+ theStateCode = ossimPlanetTextureLayer_NO_SOURCE_DATA;
+ }
+
+ return theStateCode;
+}
+bool ossimPlanetDtedElevationDatabase::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ if(!theOpenFlag)
+ {
+ return false;
+ }
+
+ if(!theEnableFlag)
+ {
+ return false;
+ }
+ ossimPlanetGrid::GridBound bound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ ossimPlanetGrid::GridBound tileBound;
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return false;
+ }
+ }
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ ossimPlanetGrid::ModelPoint minLatLon, maxLatLon;
+ grid.modelBound(tileId, minLatLon, maxLatLon);
+ if((gsd.y >= theExtents->getMinScale()) &&
+ (gsd.y <= theExtents->getMaxScale()))
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points);
+ ossim_float64 minModelX, minModelY, maxModelX, maxModelY;
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ minModelX = points[0].x();
+ maxModelX = minModelX;
+ minModelY = points[0].y();
+ maxModelY = minModelY;
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ ++optimizedOutPtr;
+ for(idxPts = 1; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if(optimizedOutPtr->x() < minModelX) minModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->x() > maxModelX) maxModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->y() < minModelY) minModelY = optimizedOutPtr->y();
+ if(optimizedOutPtr->y() > maxModelY) maxModelY = optimizedOutPtr->y();
+ }
+ ossim_int32 wholeMinY = (ossim_int32)std::floor(minModelY);
+ ossim_int32 wholeMinX = (ossim_int32)std::floor(minModelX);
+ ossim_int32 wholeMaxY = (ossim_int32)std::floor(maxModelY);
+ ossim_int32 wholeMaxX = (ossim_int32)std::floor(maxModelX);
+
+
+ ossim_int32 lat = wholeMaxY;
+ ossim_int32 lon = wholeMinX;
+
+
+ // std::vector<ossimDpt> latLonOrigins;
+ std::vector<std::string> latLonOrigins;
+
+ for(;lat >= wholeMinY; --lat)
+ {
+ lon = wholeMinX;
+ for(;lon <= wholeMaxX; ++lon)
+ {
+ ossimFilename filename = buildFilename(lat, lon);
+ if(filename != "")
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetDtedElevationDatabase::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ ossimElevManager* manager = ossimElevManager::instance();
+ double minValue = 999999999.0;
+ double maxValue = -999999999.0;
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ double h = manager->getHeightAboveEllipsoid(ossimGpt((*optimizedOutPtr).y(), (*optimizedOutPtr).x()));
+ if(!ossim::isnan(h))
+ {
+ *bufPtr = h;
+ }
+
+ ++bufPtr;
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+
+
+ return texture;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetDtedElevationDatabase::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ if(!theOpenFlag)
+ {
+ return 0;
+ }
+
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+ ossim_uint32 width = utility.getTileWidth();
+ ossim_uint32 height = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row,
+ col);
+
+ if(!theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ return 0;
+ }
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/height;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+
+ if(!theExtents->intersectsScale(gsd.y-FLT_EPSILON,
+ gsd.y+FLT_EPSILON))//gsd.y <= theExtents.theMaxGsd)
+ {
+ return 0;
+ }
+ double minSubRectLat = ossim::max(theExtents->getMinLat(),
+ minLat);
+ double minSubRectLon = ossim::max(theExtents->getMinLon(),
+ minLon);
+ double maxSubRectLat = ossim::min(theExtents->getMaxLat(),
+ maxLat);
+ double maxSubRectLon = ossim::min(theExtents->getMaxLon(),
+ maxLon);
+ ossim_int32 wholeMinLat = (ossim_int32)std::floor(minSubRectLat);
+ ossim_int32 wholeMinLon = (ossim_int32)std::floor(minSubRectLon);
+ ossim_int32 wholeMaxLat = (ossim_int32)std::floor(maxSubRectLat);
+ ossim_int32 wholeMaxLon = (ossim_int32)std::floor(maxSubRectLon);
+
+
+ ossim_int32 lat = wholeMaxLat;
+ ossim_int32 lon = wholeMinLon;
+
+
+// std::vector<ossimDpt> latLonOrigins;
+ std::vector<std::string> latLonOrigins;
+
+ for(;lat >= wholeMinLat; --lat)
+ {
+ lon = wholeMinLon;
+ for(;lon <= wholeMaxLon; ++lon)
+ {
+ ossimFilename filename = buildFilename(lat, lon);
+ if(filename != "")
+ {
+ latLonOrigins.push_back(filename);
+ }
+ }
+ }
+
+ if(latLonOrigins.size() == 0)
+ {
+ return 0;
+ }
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfFilesNeeded = latLonOrigins.size();
+ texture = new ossimPlanetImage(ossimPlanetTerrainTileId(0,
+ level,
+ col,
+ row));
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width,
+ height);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ utility.createGridPoints(points,
+ level,
+ row,
+ col,
+ height,
+ width);
+
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/DBL_EPSILON -1;
+ double maxValue = -1.0/DBL_EPSILON +1;
+ //double offset = 0.0;
+
+ for(idx = 0; idx < numberOfFilesNeeded;++idx)
+ {
+
+ osg::ref_ptr<ossimPlanetDtedElevationDatabase::DtedInfo> dtedFile = getInfo(latLonOrigins[idx]);
+
+ if(dtedFile.valid())
+ {
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ for(idxPts = 0; idxPts < nPoints; ++idxPts)
+ {
+ utility.getLatLon(latLonPoint, points[idxPts]);
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&
+ (latLonPoint[0] >= dtedFile->theMinLat)&&
+ (latLonPoint[0] <= dtedFile->theMaxLat)&&
+ (latLonPoint[1] >= dtedFile->theMinLon)&&
+ (latLonPoint[1] <= dtedFile->theMaxLon))
+ {
+ utility.getLatLon(latLonPoint, points[idxPts]);
+ ossim_float64 nullHeight = dtedFile->theHandler->getNullHeightValue();
+ double h = dtedFile->theHandler->getHeightAboveMSL(ossimGpt(latLonPoint[0],
+ latLonPoint[1]));
+ if(!ossim::isnan(h)&&
+ (h!=nullHeight))
+ {
+ if(theGeoRefModel.valid())
+ {
+ h+=theGeoRefModel->getGeoidOffset(latLonPoint[0], latLonPoint[1]);
+ }
+ *bufPtr = h;
+ if(*bufPtr < minValue)
+ {
+ minValue = *bufPtr;
+ }
+ if(*bufPtr > maxValue)
+ {
+ maxValue = *bufPtr;
+ }
+ }
+ else
+ {
+ *bufPtr = 0;
+ }
+ }
+ ++bufPtr;
+ }
+ }
+ }
+ compositeData->validate();
+
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+
+ return texture;
+
+}
+
+osg::ref_ptr<ossimPlanetDtedElevationDatabase::DtedInfo> ossimPlanetDtedElevationDatabase::getInfo(const std::string& name)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theDtedInfoMutex);
+ DtedFilePointerList::iterator iter = theFilePointers.find(name);
+
+ if(iter != theFilePointers.end())
+ {
+ iter->second->theTimeStamp = osg::Timer::instance()->tick();
+
+ return iter->second;
+ }
+ osg::ref_ptr<DtedInfo> info = new DtedInfo;
+
+ ossimFilename dtedFile = ossimFilename(theLocation).dirCat(ossimFilename(name));
+
+ ifstream in;
+
+ in.open(dtedFile.c_str(), std::ios::binary|std::ios::in);
+
+ if(in.fail()) return 0;
+
+ ossimDtedVol vol(in);
+ ossimDtedHdr hdr(in);
+ ossimDtedUhl uhl(in);
+
+ in.close();
+
+ if((uhl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR))
+ {
+ return 0;
+ }
+ info->theNumLonLines = uhl.numLonLines();
+ info->theNumLatPoints = uhl.numLatPoints();
+ info->theLatSpacing = uhl.latInterval();
+ info->theLonSpacing = uhl.lonInterval();
+ info->theMinLat = uhl.latOrigin();
+ info->theMinLon = uhl.lonOrigin();
+ info->theMaxLat = info->theMinLat + info->theLatSpacing*(info->theNumLatPoints-1);
+ info->theMaxLon = info->theMinLon + info->theLonSpacing*(info->theNumLonLines-1);
+ info->theTimeStamp = osg::Timer::instance()->tick();
+ info->theFilename = dtedFile;
+ info->theHandler = new ossimDtedHandler(dtedFile, false);
+ //info->theHandler->setMemoryMapFlag(false);
+ theFilePointers.insert(std::make_pair(name, info));
+ shrinkFilePointers();
+
+ return info;
+
+}
+
+void ossimPlanetDtedElevationDatabase::shrinkFilePointers()
+{
+ if(theFilePointers.size() <= theMaxOpenFiles) return;
+
+ const osg::Timer* timer = osg::Timer::instance();
+
+ osg::Timer_t currentTime = timer->tick();
+
+ while((theFilePointers.size()>0) &&
+ (theFilePointers.size() > theMinOpenFiles))
+ {
+ DtedFilePointerList::iterator iter = theFilePointers.begin();
+ DtedFilePointerList::iterator currentLargestTimeDelta = iter;
+ double delta = 0.0;
+ while(iter!=theFilePointers.end())
+ {
+ double testDelta = timer->delta_m(currentLargestTimeDelta->second->theTimeStamp, currentTime);
+ if(testDelta > delta)
+ {
+ currentLargestTimeDelta = iter;
+ delta = testDelta;
+ }
+ ++iter;
+ }
+
+ if(currentLargestTimeDelta != theFilePointers.end())
+ {
+ theFilePointers.erase(currentLargestTimeDelta);
+ }
+ }
+}
+
+ossimFilename ossimPlanetDtedElevationDatabase::buildFilename(double lat, double lon)const
+{
+ ossimFilename dtedFileBase;
+
+ int ilon = static_cast<int>(lon);
+
+ if (ilon < 0)
+ {
+ dtedFileBase = "w";
+ }
+ else
+ {
+ dtedFileBase = "e";
+ }
+
+ ilon = abs(ilon);
+ std::ostringstream s1;
+ s1 << std::setfill('0') << std::setw(3)<< ilon;
+
+ dtedFileBase += s1.str().c_str();//ossimString::toString(ilon);
+ dtedFileBase += "/";
+
+ int ilat = static_cast<int>(floor(lat));
+ if (ilat < 0)
+ {
+ dtedFileBase += "s";
+ }
+ else
+ {
+ dtedFileBase += "n";
+ }
+
+ ilat = abs(ilat);
+ std::ostringstream s2;
+
+ s2<< std::setfill('0') << std::setw(2)<< ilat;
+
+ dtedFileBase += s2.str().c_str();
+
+ ossimFilename tempDir(theLocation);
+ // Look for a dted file with a level 3 extension first.
+ ossimFilename dtedName = tempDir.dirCat(dtedFileBase);
+ dtedName += ".dt3";
+
+ if (dtedName.exists())
+ {
+ return dtedFileBase + ".dt3";
+ }
+
+ // Look for a dted file with a level 2 extension next.
+ dtedName = tempDir.dirCat(dtedFileBase);
+ dtedName += ".dt2";
+
+ if(dtedName.exists())
+ {
+ return dtedFileBase + ".dt2";
+ }
+
+ // Look for a dted file with a level 1 extension next.
+ dtedName = tempDir.dirCat(dtedFileBase);
+ dtedName += ".dt1";
+ if(dtedName.exists())
+ {
+ return dtedFileBase + ".dt1";
+ }
+
+ // Look for a dted file with a level 0 extension next.
+ dtedName = tempDir.dirCat(dtedFileBase);
+ dtedName += ".dt0";
+ if(dtedName.exists())
+ {
+ return dtedFileBase + ".dt0";
+ }
+
+ return "";
+}
+
+osg::ref_ptr<ossimPlanetDtedElevationDatabase::DtedInfo> ossimPlanetDtedElevationDatabase::findDtedInfo(const std::string& name)
+{
+ DtedFilePointerList::iterator iter = theFilePointers.find(name);
+
+ if(iter != theFilePointers.end())
+ {
+ iter->second->theTimeStamp = osg::Timer::instance()->tick();
+ return iter->second;
+ }
+
+ return 0;
+
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetElevationDatabase.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationDatabase.cpp
new file mode 100644
index 0000000..8b5beb5
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationDatabase.cpp
@@ -0,0 +1,92 @@
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetElevationDatabase::getTexture(const ossimPlanetTerrainTileId& tileId,
+ osg::ref_ptr<ossimPlanetGrid> theGrid)
+{
+ return 0;
+}
+
+void ossimPlanetElevationDatabase::mergeDataObjects(ossimRefPtr<ossimImageData> destData,
+ ossimRefPtr<ossimImageData> srcData)
+{
+ if(destData.valid()&&srcData.valid()&&
+ destData->getBuf()&&srcData->getBuf())
+ {
+ if((destData->getScalarType() == OSSIM_FLOAT)&&
+ (destData->getWidth()==srcData->getWidth())&&
+ (destData->getHeight()==srcData->getHeight()))
+ {
+ ossim_float32* destBuf = (ossim_float32*)destData->getBuf();
+ ossim_float32 destNp = (ossim_float32)destData->getNullPix(0);
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = destData->getWidth()*destData->getHeight();
+
+ switch(srcData->getScalarType())
+ {
+ case OSSIM_UINT16:
+ case OSSIM_USHORT11:
+ {
+ ossim_uint16* srcBuf = (ossim_uint16*)srcData->getBuf();
+ ossim_uint16 srcNp = (ossim_uint16)srcData->getNullPix(0);
+
+ for(;idx < area; ++idx)
+ {
+ if(*destBuf == destNp)
+ {
+ if(*srcBuf != srcNp)
+ {
+ *destBuf = (ossim_float32)*srcBuf;
+ }
+ }
+ ++destBuf;
+ ++srcBuf;
+ }
+ break;
+ }
+ case OSSIM_SINT16:
+ {
+ ossim_sint16* srcBuf = (ossim_sint16*)srcData->getBuf();
+ ossim_sint16 srcNp = (ossim_sint16)srcData->getNullPix(0);
+
+ for(;idx < area; ++idx)
+ {
+ if(*destBuf == destNp)
+ {
+ if(*srcBuf != srcNp)
+ {
+ *destBuf = (ossim_float32)*srcBuf;
+ }
+ }
+ ++destBuf;
+ ++srcBuf;
+ }
+ break;
+ }
+ case OSSIM_FLOAT32:
+ {
+ ossim_float32* srcBuf = (ossim_float32*)srcData->getBuf();
+ ossim_float32 srcNp = (ossim_float32)srcData->getNullPix(0);
+
+ for(;idx < area; ++idx)
+ {
+ if(*destBuf == destNp)
+ {
+ if(*srcBuf != srcNp)
+ {
+ *destBuf = *srcBuf;
+ }
+ }
+ ++destBuf;
+ ++srcBuf;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ // not supported
+ }
+ }
+ }
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetElevationDatabaseGroup.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationDatabaseGroup.cpp
new file mode 100644
index 0000000..6d22dc4
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationDatabaseGroup.cpp
@@ -0,0 +1,518 @@
+#include <ossimPlanet/ossimPlanetElevationDatabaseGroup.h>
+#include <ossimPlanet/ossimPlanetElevationDatabase.h>
+#include <stack>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimGpt.h>
+
+ossimPlanetElevationDatabaseGroup::ossimPlanetElevationDatabaseGroup()
+ :ossimPlanetTextureLayerGroup(),
+ theFillNullWithGeoidOffsetFlag(false)
+{
+}
+
+ossimPlanetElevationDatabaseGroup::ossimPlanetElevationDatabaseGroup(const ossimPlanetElevationDatabaseGroup& src)
+:ossimPlanetTextureLayerGroup(src),
+theFillNullWithGeoidOffsetFlag(src.theFillNullWithGeoidOffsetFlag)
+{
+}
+
+ossimPlanetTextureLayer* ossimPlanetElevationDatabaseGroup::dup()const
+{
+ return new ossimPlanetElevationDatabaseGroup(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetElevationDatabaseGroup::dupType()const
+{
+ return new ossimPlanetElevationDatabaseGroup;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetElevationDatabaseGroup::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT);
+ compositeData->initialize();
+ osg::ref_ptr<ossimPlanetImage> result = new ossimPlanetImage(tileId);
+ result->fromOssimImage(compositeData, false);
+ result->setPadding(padding);
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ bool withinExtents = true;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ withinExtents = false;
+ }
+ }
+ else
+ {
+ withinExtents = false;
+ }
+ ossim_uint32 idx = 0;
+ for(idx = 0; (idx < theChildrenList.size())&&withinExtents&&getEnableFlag(); ++idx)
+ {
+ if(theChildrenList[idx].valid())
+ {
+ const osg::ref_ptr<ossimPlanetExtents> extents = theChildrenList[idx]->getExtents();
+
+ if(extents.valid())
+ {
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(extents->getMinLon(), extents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(extents->getMaxLon(), extents->getMaxLat()),
+ bound))
+ {
+// std::cout << "TESTING INTERSECTS" << std::endl;
+// std::cout << "tileBound = " << tileBound.toDrect() << std::endl
+// << "fullBound = " << bound.toDrect() << std::endl;
+ if(tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ osg::ref_ptr<ossimPlanetImage> image = theChildrenList[idx]->getTexture(width,
+ height,
+ tileId,
+ grid,
+ padding);
+ if(image.valid())
+ {
+ if(result.valid())
+ {
+ mergeImage(image.get(), result.get());
+ result = image;
+ if(result->getPixelStatus() == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ return result;
+ }
+ }
+ else
+ {
+ result = (ossimPlanetImage*)image->clone(osg::CopyOp::DEEP_COPY_ALL);
+ if(result->getPixelStatus() == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ return result;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if((result->getPixelStatus() != ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)&&
+ (theFillNullWithGeoidOffsetFlag)&&
+ (theGeoRefModel.valid()))
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ result->padding());
+
+ ossim_uint32 nPoints = points.size();
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/FLT_EPSILON -1;
+ double maxValue = -1.0/FLT_EPSILON +1;
+ ossim_float32* bufPtr = (ossim_float32*)result->data();
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ for(idx = 0; idx < nPoints; ++idx,++optimizedOutPtr)
+ {
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)||
+ (ossim::isnan(*bufPtr)))
+ {
+ *bufPtr = theGeoRefModel->getGeoidOffset(ossim::clamp(optimizedOutPtr->y(),-90.0, 90.0),
+ ossim::wrap(optimizedOutPtr->x(), -180.0, 180.0));
+ }
+ if(ossim::isnan(*bufPtr))
+ {
+ *bufPtr = 0;
+ }
+ else if(*bufPtr < minValue)
+ {
+ minValue = *bufPtr;
+ }
+ else if(*bufPtr > maxValue)
+ {
+ maxValue = *bufPtr;
+ }
+ ++bufPtr;
+ }
+
+ if(minValue < maxValue)
+ {
+ result->setMinMax(minValue, maxValue);
+ }
+ result->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_FULL);
+ }
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetElevationDatabaseGroup::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ ossim_uint32 width = utility.getTileWidth();
+ ossim_uint32 height = utility.getTileHeight();
+
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width,
+ height);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT);
+ compositeData->initialize();
+ osg::ref_ptr<ossimPlanetImage> result = new ossimPlanetImage(ossimPlanetTerrainTileId(0, level, col, row));
+
+ result->fromOssimImage(compositeData, false);
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ ossim_uint32 idx = 0;
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+// unsigned int w = utility.getTileWidth();
+ unsigned int h = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row,
+ col );
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/h;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon)&&
+ theExtents->intersectsScale(gsd.y,
+ gsd.y)&&
+ getEnableFlag())
+ {
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ if(theChildrenList[idx].valid())
+ {
+ const osg::ref_ptr<ossimPlanetExtents> extents = theChildrenList[idx]->getExtents();
+
+ if(extents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ osg::ref_ptr<ossimPlanetImage> image = theChildrenList[idx]->getTexture(level, row, col, utility);
+ if(image.valid())
+ {
+ if(result.valid())
+ {
+ mergeImage(image.get(), result.get());
+ result = image;
+ if(result->getPixelStatus() == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ return result;
+ }
+ }
+ else
+ {
+ result = (ossimPlanetImage*)image->clone(osg::CopyOp::DEEP_COPY_ALL);
+ if(result->getPixelStatus() == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ return result;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if((result->getPixelStatus() != ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)&&
+ (theFillNullWithGeoidOffsetFlag)&&
+ (theGeoRefModel.valid()))
+ {
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ utility.createGridPoints(points,
+ level,
+ row,
+ col,
+ height,
+ width);
+
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/FLT_EPSILON -1;
+ double maxValue = -1.0/FLT_EPSILON +1;
+ ossim_float32* bufPtr = (ossim_float32*)result->data();
+ for(idxPts = 0; idxPts < nPoints; ++idxPts)
+ {
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)||
+ (ossim::isnan(*bufPtr)))
+ {
+ utility.getLatLon(latLonPoint, points[idxPts]);
+
+ *bufPtr = theGeoRefModel->getGeoidOffset(latLonPoint[0], latLonPoint[1]);
+ }
+ if(*bufPtr < minValue)
+ {
+ minValue = *bufPtr;
+ }
+ if(*bufPtr > maxValue)
+ {
+ maxValue = *bufPtr;
+ }
+ ++bufPtr;
+ }
+
+ if(minValue < maxValue)
+ {
+ result->setMinMax(minValue, maxValue);
+ }
+ result->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_FULL);
+ }
+ return result;
+
+}
+
+bool ossimPlanetElevationDatabaseGroup::replaceLayer(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layer.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::replaceLayer(idx, layer.get());
+ }
+
+ return false;
+}
+
+bool ossimPlanetElevationDatabaseGroup::addTop(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layer.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::addTop(layer.get());
+ }
+
+ return false;
+}
+
+bool ossimPlanetElevationDatabaseGroup::addBeforeIdx(ossim_uint32 idx, osg::ref_ptr<ossimPlanetTextureLayer> layer)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layer.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::addBeforeIdx(idx, layer.get());
+ }
+
+ return false;
+}
+
+bool ossimPlanetElevationDatabaseGroup::addBeforeLayer(const osg::ref_ptr<ossimPlanetTextureLayer> beforeLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layerToAdd.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::addBeforeLayer(beforeLayer.get(),
+ layerToAdd.get());
+ }
+
+ return false;
+}
+
+bool ossimPlanetElevationDatabaseGroup::addAfterIdx(ossim_int32 idx, osg::ref_ptr<ossimPlanetTextureLayer> layer)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layer.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::addAfterIdx(idx, layer.get());
+ }
+
+ return false;
+}
+
+bool ossimPlanetElevationDatabaseGroup::addAfterLayer(const osg::ref_ptr<ossimPlanetTextureLayer> afterLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layerToAdd.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::addAfterLayer(afterLayer.get(),
+ layerToAdd.get());
+
+ }
+
+ return false;
+}
+
+bool ossimPlanetElevationDatabaseGroup::addBottom(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+{
+ ossimPlanetElevationDatabase* databaseLayer = dynamic_cast<ossimPlanetElevationDatabase*>(layer.get());
+ if(databaseLayer)
+ {
+ databaseLayer->setGeoRefModel(theGeoRefModel.get());
+ return ossimPlanetTextureLayerGroup::addBottom(layer.get());
+ }
+
+ return false;
+}
+
+void ossimPlanetElevationDatabaseGroup::mergeImage(ossimPlanetImage* result,
+ const ossimPlanetImage* source)const
+{
+ if(result&&source)
+ {
+
+ if((source->getDataType() == GL_FLOAT)&&
+ (source->getPixelFormat()== GL_LUMINANCE)&&
+ (result->getDataType() == GL_FLOAT)&&
+ (result->getPixelFormat()== GL_LUMINANCE)&&
+ (result->s() == source->s())&&
+ (result->t() == source->t()))
+ {
+ const ossim_float32* srcPtr = reinterpret_cast<const ossim_float32*>(source->data());
+ ossim_float32* resultPtr = reinterpret_cast<ossim_float32*>(result->data());
+ ossim_uint32 area = source->s()*source->t();
+
+ if(area>0)
+ {
+ ossim_uint32 idx = 0;
+ ossim_uint32 nullCount = 0;
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(*resultPtr == OSSIMPLANET_NULL_HEIGHT)
+ {
+ if(*srcPtr != OSSIMPLANET_NULL_HEIGHT)
+ {
+ *resultPtr = *srcPtr;
+ }
+ else
+ {
+ ++nullCount;
+ }
+ }
+ ++resultPtr;
+ ++srcPtr;
+ }
+
+ if(nullCount < 1)
+ {
+ result->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_FULL);
+ }
+ else if(nullCount == area)
+ {
+ result->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_EMPTY);
+ }
+ else if(nullCount > 0)
+ {
+ result->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_PARTIAL);
+ }
+ }
+ else
+ {
+ result->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_EMPTY);
+ }
+ if(source->hasMinMax())
+ {
+ if(result->hasMinMax())
+ {
+ ossim_uint32 idx = 0;
+ ossim_uint32 maxCount = ossim::max(source->minValue().size(), result->minValue().size());
+ for(;idx < maxCount; ++idx)
+ {
+ result->setMin(idx,
+ ossim::min(source->minValue()[idx],
+ result->minValue()[idx]));
+ result->setMax(idx,
+ ossim::max(source->maxValue()[idx],
+ result->maxValue()[idx]));
+ }
+ }
+ else
+ {
+ result->setMinMax(source->minValue(),
+ source->maxValue());
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetElevationDatabaseGroup::setPixelStatus(ossimPlanetImage* image)
+{
+ if((image->getDataType() == GL_FLOAT)&&
+ (image->getPixelFormat()== GL_LUMINANCE))
+ {
+ ossim_uint32 area = image->s()*image->t();
+ ossim_uint32 nullCount = 0;
+ ossim_uint32 idx = 0;
+ ossim_float32* imagePtr = reinterpret_cast<ossim_float32*>(image->data());
+ image->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_EMPTY);
+
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(*imagePtr == OSSIMPLANET_NULL_HEIGHT)
+ {
+ ++nullCount;
+ }
+ ++imagePtr;
+ }
+ if(nullCount == area)
+ {
+ image->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_EMPTY);
+ }
+ else if(nullCount > 0)
+ {
+ image->setPixelStatus(ossimPlanetImage::ossimPlanetImagePixelStatus_PARTIAL);
+ }
+ }
+}
+
+void ossimPlanetElevationDatabaseGroup::setGeoRefModel(osg::ref_ptr<ossimPlanetGeoRefModel> model)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ theGeoRefModel = model.get();
+ ossim_uint32 bound = theChildrenList.size();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < bound; ++idx)
+ {
+ ossimPlanetElevationDatabase* database = dynamic_cast<ossimPlanetElevationDatabase*>(theChildrenList[idx].get());
+ if(database)
+ {
+ database->setGeoRefModel(model.get());
+ }
+ }
+}
+
+void ossimPlanetElevationDatabaseGroup::setFillNullWithGeoidOffsetFlag(bool flag)
+{
+ theFillNullWithGeoidOffsetFlag = flag;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetElevationFactory.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationFactory.cpp
new file mode 100644
index 0000000..3574119
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationFactory.cpp
@@ -0,0 +1,49 @@
+#include <ossimPlanet/ossimPlanetElevationFactory.h>
+#include <ossimPlanet/ossimPlanetSrtmElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetDtedElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.h>
+
+ossimPlanetElevationFactory::ossimPlanetElevationFactory()
+{
+ setId("default");
+}
+
+ossimPlanetElevationFactory* ossimPlanetElevationFactory::instance()
+{
+ static ossimPlanetElevationFactory* theInstance = 0;
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetElevationFactory;
+ }
+
+ return theInstance;
+}
+
+ossimPlanetElevationDatabase* ossimPlanetElevationFactory::openDatabase(const ossimString& location)
+{
+ // check SRTM database
+ osg::ref_ptr<ossimPlanetElevationDatabase> database = new ossimPlanetSrtmElevationDatabase;
+
+ if(database->open(location) == ossimPlanetTextureLayer_VALID)
+ {
+ return database.release();
+ }
+ else
+ {
+ database = new ossimPlanetDtedElevationDatabase;
+ if(database->open(location) == ossimPlanetTextureLayer_VALID)
+ {
+ return database.release();
+ }
+ else
+ {
+ database = new ossimPlanetGeneralRasterElevationDatabase;
+ if(database->open(location) == ossimPlanetTextureLayer_VALID)
+ {
+ return database.release();
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetElevationGrid.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationGrid.cpp
new file mode 100644
index 0000000..9228e23
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationGrid.cpp
@@ -0,0 +1,174 @@
+#include <ossimPlanet/ossimPlanetElevationGrid.h>
+#include <iostream>
+#include <ossim/base/ossimCommon.h>
+ossimPlanetElevationGrid::ossimPlanetElevationGrid(ossim_uint32 w,
+ ossim_uint32 h)
+{
+ theGrid = 0;
+ theWidth = 0;
+ theHeight = 0;
+ resize(w,h);
+}
+
+ossimPlanetElevationGrid::~ossimPlanetElevationGrid()
+{
+ if(theGrid)
+ {
+ delete [] theGrid;
+ theGrid = 0;
+ }
+}
+
+void ossimPlanetElevationGrid::resize(ossim_uint32 w,
+ ossim_uint32 h)
+{
+ if(theGrid)
+ {
+ delete [] theGrid;
+ theGrid = 0;
+ }
+ theGrid = new float[w*h];
+
+ theWidth = w;
+ theHeight = h;
+}
+
+osg::ref_ptr<ossimPlanetElevationGrid> ossimPlanetElevationGrid::scaleBy2Nearest()const
+{
+ // note our elevation has one extra row and 1 extra column so the
+ // scaled should be 2*(height-1) + 1 and 2*(width-1) + 1 for
+ // the new dimensions
+ //
+// ossim_uint32 outputWidth = ((theWidth-1) <<1) + 1;
+// ossim_uint32 outputHeight = ((theHeight-1)<<1) + 1;
+ ossim_uint32 outputWidth = theWidth<<1;
+ ossim_uint32 outputHeight = theHeight<<1;
+ osg::ref_ptr<ossimPlanetElevationGrid> result = new ossimPlanetElevationGrid(outputWidth,
+ outputHeight);
+ ossim_uint32 y = 0;
+ ossim_uint32 x = 0;
+ const float* inputData = theGrid;
+ float* outputData = result->theGrid;
+ ossim_uint32 inputOffsetY = 0;
+ ossim_uint32 inputOffset = 0;
+ for(y = 0; y < outputHeight; ++y)
+ {
+ inputOffsetY = (y>>1)*theWidth;
+ for(x = 0; x < outputWidth; ++x)
+ {
+ inputOffset = inputOffsetY + (x>>1);
+ *outputData= inputData[inputOffset];
+ ++outputData;
+ }
+ }
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetElevationGrid> ossimPlanetElevationGrid::scaleBy2Bilinear()const
+{
+// ossim_uint32 outputWidth = theWidth<<1;
+// ossim_uint32 outputHeight = theHeight<<1;
+ ossim_uint32 outputWidth = ( ((theWidth-1)<<1) + 1);
+ ossim_uint32 outputHeight = ( ((theHeight-1)<<1) + 1);
+ osg::ref_ptr<ossimPlanetElevationGrid> result = new ossimPlanetElevationGrid(outputWidth,
+ outputHeight);
+ ossim_uint32 y = 0;
+ ossim_uint32 x = 0;
+ const float* inputData = theGrid;
+ float* outputData = result->theGrid;
+ ossim_uint32 inputOffsetY = 0;
+ ossim_uint32 inputOffset = 0;
+ ossim_uint8 testLocation=0;
+ for(y = 0; y < outputHeight; ++y)
+ {
+ inputOffsetY = (y>>1)*theWidth;
+ for(x = 0; x < outputWidth; ++x)
+ {
+ inputOffset = inputOffsetY + (x>>1);
+ testLocation = ((y&1) << 1) | (x&1);
+ switch(testLocation)
+ {
+ case 0: // upper left
+ {
+ // just copy the point
+ *outputData = inputData[inputOffset];
+
+ break;
+ }
+ case 1: // upper right
+ {
+ // do horizontal t for x edge
+ *outputData = (inputData[inputOffset] +
+ inputData[inputOffset+1])*.5;
+ break;
+ }
+ case 2: // lower left
+ {
+ // do vertical t for y edge
+ *outputData = (inputData[inputOffset] +
+ inputData[inputOffset+theWidth])*.5;
+
+ break;
+ }
+ case 3: // lower right
+ {
+ // do both horizontal and vertical using all 4 points
+ *outputData = (inputData[inputOffset] +
+ inputData[inputOffset+theWidth]+
+ inputData[inputOffset+theWidth+1]+
+ inputData[inputOffset+1]
+ )*.25;
+ break;
+ }
+ }
+ ++outputData;
+ }
+ }
+ return result;
+}
+
+void ossimPlanetElevationGrid::copyGrid(ossim_uint32 ulx,
+ ossim_uint32 uly,
+ osg::ref_ptr<ossimPlanetElevationGrid> output)const
+{
+ if(!output.valid()) return;
+ ossim_uint32 outputWidth = output->getWidth();
+ ossim_uint32 outputHeight = output->getHeight();
+ ossim_float32 *outputBuf = output->theGrid;
+ const ossim_float32 *inputBuf = theGrid;
+ ossim_uint32 leftOffset = 0;
+ ossim_uint32 x = 0;
+ ossim_uint32 y = 0;
+
+ leftOffset = uly*theWidth + ulx;
+ for(y=0;y < outputHeight;++y)
+ {
+ for(x=0;x < outputWidth; ++x)
+ {
+ *outputBuf = inputBuf[leftOffset+x];
+ ++outputBuf;
+ }
+ leftOffset += theWidth;
+ }
+}
+
+bool ossimPlanetElevationGrid::isEqualTo(osg::ref_ptr<ossimPlanetElevationGrid> grid)const
+{
+ if(!grid.valid()) return false;
+ if(grid.get() == this) return true;
+ if( (grid->theWidth!=theWidth)||
+ (grid->theHeight != theHeight) ) return false;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 upperBound = theWidth*theHeight;
+
+ for(idx = 0; idx < upperBound;++idx)
+ {
+ if(theGrid[idx] != grid->theGrid[idx])
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetElevationRegistry.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationRegistry.cpp
new file mode 100644
index 0000000..1f863ab
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetElevationRegistry.cpp
@@ -0,0 +1,61 @@
+#include <ossimPlanet/ossimPlanetElevationRegistry.h>
+#include <ossimPlanet/ossimPlanetElevationFactory.h>
+#include <OpenThreads/ScopedLock>
+#include <algorithm>
+
+ossimPlanetElevationRegistry::ossimPlanetElevationRegistry()
+{
+}
+
+bool ossimPlanetElevationRegistry::registerFactory(FactoryBase* factory)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ bool result = false;
+ FactoryList::iterator iter = std::find(theFactoryList.begin(), theFactoryList.end(), factory);
+
+ if(iter == theFactoryList.end())
+ {
+ theFactoryList.push_back(factory);
+ result = true;
+ }
+
+ return result;
+}
+
+void ossimPlanetElevationRegistry::unregisterFactory(FactoryBase* factory)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ FactoryList::iterator iter = std::find(theFactoryList.begin(), theFactoryList.end(), factory);
+
+ if(iter != theFactoryList.end())
+ {
+ theFactoryList.erase(iter);
+ }
+}
+
+ossimPlanetElevationDatabase* ossimPlanetElevationRegistry::openDatabase(const ossimString& location)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimPlanetElevationDatabase* result = 0;
+
+ FactoryList::iterator iter = theFactoryList.begin();
+ while(!result&&(iter != theFactoryList.end()))
+ {
+ result = (*iter)->openDatabase(location);
+ ++iter;
+ }
+
+ return result;
+}
+
+ossimPlanetElevationRegistry* ossimPlanetElevationRegistry::instance()
+{
+ static ossimPlanetElevationRegistry* theInstance = 0;
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetElevationRegistry();
+ theInstance->registerFactory(ossimPlanetElevationFactory::instance());
+ }
+
+ return theInstance;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetEphemeris.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetEphemeris.cpp
new file mode 100644
index 0000000..d55f82e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetEphemeris.cpp
@@ -0,0 +1,2508 @@
+#ifdef OSSIMPLANET_ENABLE_EPHEMERIS
+#include <osg/ShapeDrawable>
+#include <osg/PositionAttitudeTransform>
+#include <osg/io_utils>
+//#include <gpstk/Geodetic.hpp>
+#include <gpstk/SunPosition.hpp>
+#include <gpstk/MoonPosition.hpp>
+#include <gpstk/Position.hpp>
+#include <gpstk/WGS84Ellipsoid.hpp>
+#include <gpstk/SystemTime.hpp>
+#include <gpstk/ReferenceFrame.hpp>
+//#include <gpstk/ECEF.hpp>
+//#include <gpstk/WGS84Geoid.hpp>
+#include <ossimPlanet/ossimPlanetEphemeris.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetPointModel.h>
+#include <ossimPlanet/ossimPlanetBillboardIcon.h>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetCloudLayer.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/imaging/ossimJpegWriter.h>
+#include <ossim/imaging/ossimMemoryImageSource.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <osg/CoordinateSystemNode>
+#include <osg/VertexProgram>
+#include <osg/Fog>
+#include <osg/Camera>
+#include <osg/io_utils>
+#include <osg/Depth>
+#include <osg/BlendFunc>
+#include <osg/AlphaFunc>
+#include <osg/FragmentProgram>
+#include <osgGA/EventVisitor>
+#include <osgUtil/IntersectVisitor>
+#include <osgUtil/IntersectionVisitor>
+
+#include <osg/io_utils>
+#include <time.h>
+#include <osgDB/Registry>
+#include <osgDB/ReadFile>
+#include <osgDB/WriteFile>
+#include <queue>
+
+
+
+
+class EnvEffect : public osg::Referenced
+{
+public:
+
+ EnvEffect( const std::string& name = "EnvEffect" )
+ {
+
+ }
+
+protected:
+
+ virtual ~EnvEffect()
+ {
+
+ }
+
+public:
+
+ /// Must override this to supply the repainting routine
+ virtual void Repaint(const osg::Vec3& skyColor,
+ const osg::Vec3& fogColor,
+ double sunAngle,
+ double sunAzimuth,
+ double visibility,
+ double altitude=0.0) = 0;
+
+ ///required by DeltaDrawable
+ osg::Node* GetOSGNode(){return mNode.get();}
+ const osg::Node* GetOSGNode() const{return mNode.get();}
+
+ void SetOSGNode(osg::Node* pNode){mNode = pNode;}
+
+private:
+
+ // Disallowed to prevent compile errors on VS2003. It apparently
+ // creates this functions even if they are not used, and if
+ // this class is forward declared, these implicit functions will
+ // cause compiler errors for missing calls to "ref".
+ EnvEffect& operator=( const EnvEffect& );
+ EnvEffect( const EnvEffect& );
+
+ osg::ref_ptr<osg::Node> mNode;
+};
+
+class MoveEarthySkyWithEyePointTransform : public osg::Transform
+{
+public:
+
+ ///Get the transformation matrix which moves from local coords to world coords.
+ virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
+
+ ///Get the transformation matrix which moves from world coords to local coords.
+ virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
+};
+
+class MoveEarthySkyWithEyePointTransformAzimuth : public osg::Transform
+{
+public:
+
+ ///Get the transformation matrix which moves from local coords to world coords.
+ virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
+
+ ///Get the transformation matrix which moves from world coords to local coords.
+ virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
+
+ float GetAzimuth() const { return mAzimuth; }
+ void SetAzimuth( float azimuth ) { mAzimuth = azimuth; }
+
+private:
+
+ float mAzimuth;
+};
+bool MoveEarthySkyWithEyePointTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
+{
+ if ( osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv) )
+ {
+ osg::Vec3 eyePointLocal = cv->getEyeLocal();
+ matrix.preMult(osg::Matrix::translate(eyePointLocal.x(),eyePointLocal.y(),eyePointLocal.z()));
+ }
+ return true;
+}
+
+///Get the transformation matrix which moves from world coords to local coords.
+bool MoveEarthySkyWithEyePointTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
+{
+ if ( osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv) )
+ {
+ osg::Vec3 eyePointLocal = cv->getEyeLocal();
+ matrix.postMult(osg::Matrix::translate(-eyePointLocal.x(),-eyePointLocal.y(),-eyePointLocal.z()));
+ }
+ return true;
+}
+
+///Get the transformation matrix which moves from local coords to world coords.
+bool MoveEarthySkyWithEyePointTransformAzimuth::computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
+{
+ if ( osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv) )
+ {
+ osg::Vec3 eyePointLocal = cv->getEyeLocal();
+ matrix.preMult(osg::Matrix::translate(eyePointLocal.x(),eyePointLocal.y(),eyePointLocal.z()));
+ matrix.preMult(osg::Matrix::rotate(osg::DegreesToRadians(mAzimuth-90.0f), 0.0f, 0.0f, 1.0f));
+ }
+ return true;
+}
+
+///Get the transformation matrix which moves from world coords to local coords.
+bool MoveEarthySkyWithEyePointTransformAzimuth::computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
+{
+ if ( osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv) )
+ {
+ osg::Vec3 eyePointLocal = cv->getEyeLocal();
+ matrix.postMult(osg::Matrix::translate(-eyePointLocal.x(),-eyePointLocal.y(),-eyePointLocal.z()));
+ }
+ return true;
+}
+
+class SkyDomeShader : public osg::Referenced
+{
+public:
+ SkyDomeShader()
+ {
+ mLightScatterinVP = new osg::VertexProgram();
+ mDomeFP = new osg::FragmentProgram();
+
+ char data[] =
+ "!!ARBvp1.0 \n"
+ " \n"
+ " PARAM mvp[4] = { state.matrix.mvp }; \n"
+ " PARAM camera = program.local[0]; \n"
+ " PARAM dir = program.local[1]; \n"
+ " PARAM betaRay = program.local[2]; \n"
+ " PARAM betaMie = program.local[3]; \n"
+ " \n"
+ " # Energy / (betaRay + betaMie) \n"
+ " PARAM energyOverRayMie = program.local[4]; \n"
+ " \n"
+ " # G = greenstein \n"
+ " # (-G * 2.0, G * G + 1.0, (1.0 - G) * (1.0 - G)) \n"
+ " PARAM greenstein = program.local[5]; \n"
+ " \n"
+ " PARAM time = program.local[6]; \n"
+ " \n"
+ " ATTRIB xyz = vertex.position; \n"
+ " ATTRIB texcoord = vertex.texcoord; \n"
+ " ATTRIB norm = vertex.normal; \n"
+ " \n"
+ " DP4 result.position.x, mvp[0], xyz; \n"
+ " DP4 result.position.y, mvp[1], xyz; \n"
+ " DP4 result.position.z, mvp[2], xyz; \n"
+ " DP4 result.position.w, mvp[3], xyz; \n"
+ " \n"
+ " TEMP temp; \n"
+ " SUB temp, camera, xyz; \n"
+ " DP3 temp.w, temp, temp; \n"
+ " RSQ temp.w, temp.w; \n"
+ " MUL temp, temp, temp.w; \n"
+ " \n"
+ " TEMP cos; \n"
+ " DP3 cos.x, temp, dir; \n"
+ " MUL cos.y, cos.x, cos.x; # cos * cos \n"
+ " SUB cos.z, 1.0, cos.y; # 1.0 - cos * cos \n"
+ " \n"
+ " TEMP ray; \n"
+ " MUL ray, cos.z, 0.0597; # 3.0 / (16.0 * PI) \n"
+ " MUL ray, ray, betaRay; \n"
+ " \n"
+ " TEMP mie; \n"
+ " MAD mie, greenstein.x, cos.x, greenstein.y; \n"
+ " MOV cos.w, 1.5; \n"
+ " POW mie.x, mie.x, cos.w; \n"
+ " RCP mie.x, mie.x; \n"
+ " MUL mie, mie.x, greenstein.z; \n"
+ " MUL mie, mie, 0.0796; # 1.0 / (4.0 * PI) \n"
+ " MUL mie, mie, betaMie; \n"
+ " \n"
+ " SUB temp, camera, xyz; \n"
+ " DP3 temp.w, temp, temp; \n"
+ " RSQ temp.w, temp.w; \n"
+ " RCP temp.w, temp.w; # distance to camera \n"
+ " \n"
+ " TEMP fog; \n"
+ " ADD fog, betaRay, betaMie; \n"
+ " MUL fog, fog, temp.w; \n"
+ " MUL fog, fog, 0.693; # ln(2.0) \n"
+ " \n"
+ " EX2 fog.x, -fog.x; \n"
+ " EX2 fog.y, -fog.y; \n"
+ " EX2 fog.z, -fog.z; \n"
+ " \n"
+ " SUB temp, 1.0, fog; # 1.0 - fog \n"
+ " \n"
+ " TEMP scattering; \n"
+ " ADD scattering, ray, mie; \n"
+ " MUL scattering, scattering, energyOverRayMie; \n"
+ " MUL scattering, scattering, temp; \n"
+ " \n"
+ " MOV result.texcoord[0], texcoord; \n"
+ " MOV result.texcoord[1], scattering; \n"
+ " MOV result.texcoord[2], fog; \n"
+ " MOV result.texcoord[3], norm; \n"
+ " MOV result.color, vertex.color; \n"
+ " END \n";
+
+ mLightScatterinVP->setVertexProgram(data);
+
+ char data2[] =
+ "!!ARBfp1.0 \n"
+ " \n"
+ " # brightness, contrast \n"
+ " PARAM bc = program.local[0]; \n"
+ " \n"
+ " TEMP clouds; \n"
+ " MOV clouds, fragment.color; \n"
+ " \n"
+ " TEMP color; \n"
+ " LRP color, fragment.texcoord[2], clouds, fragment.texcoord[1]; \n"
+ " \n"
+ " TEMP temp; \n"
+ " SUB temp, color, 0.5; \n"
+ " MAD color, temp, bc.y, color; \n"
+ " ADD result.color, color, bc.x; \n"
+ " \n"
+ " END \n";
+ mDomeFP->setFragmentProgram( data2 );
+
+ lambda = osg::Vec3(1.0f/650e-9f, 1.0f/570e-9f, 1.0f/475e-9f);
+
+ for (int i = 0; i < 3; i++)
+ {
+ lambda2[i] = lambda[i] * lambda[i];
+ lambda4[i] = lambda2[i] * lambda2[i];
+ }
+
+ //constants
+ n = 1.003f; //refractive index of air
+ pn = 0.035f; //depolarization factor of air
+
+ mBrightness = 0.125f;
+ mContrast = 0.15f;
+
+ greenstein = 0.8f * 1.5f; ///< Magic number
+
+ }
+ virtual ~SkyDomeShader(){
+ }
+
+ ///Update the shader with new values
+ void Update(const osg::Vec3d& sunVec,//const osg::Vec2& sunDir,
+ float turbidity,
+ float energy,
+ float molecules )
+ {
+ mLightScatterinVP->setProgramLocalParameter(0, osg::Vec4(0.f, 0.f, 0.f, 0.f) );
+ mLightScatterinVP->setProgramLocalParameter(1, osg::Vec4( sunVec[0], sunVec[1], sunVec[2], 0));
+
+ float tempMie = 0.434 * ConcentrationFactor(turbidity) * osg::PI * (2 * osg::PI) * (2 * osg::PI) * 0.5;
+ betaMie = osg::Vec3(lambda2[0] * 0.685,lambda2[1] * 0.679,lambda2[2] * 0.67) * tempMie;
+
+ //Rayleigh scattering
+ float tempRay = osg::PI * osg::PI * (n * n - 1.0) * (n * n - 1.0) * (6.0 + 3.0 * pn) / (6.0 - 7.0 * pn) / molecules;
+ betaRay = lambda4 * 8.0 * tempRay * osg::PI / 3.0;
+
+ mLightScatterinVP->setProgramLocalParameter(2, osg::Vec4(betaRay,0) );
+ mLightScatterinVP->setProgramLocalParameter(3, osg::Vec4(betaMie, 0));
+ mLightScatterinVP->setProgramLocalParameter(4, osg::Vec4(energy / (betaRay[0] + betaMie[0]),
+ energy / (betaRay[1] + betaMie[1]),
+ energy / (betaRay[2] + betaMie[2]),0));
+ mLightScatterinVP->setProgramLocalParameter(5, osg::Vec4(-greenstein * 2.0,
+ greenstein * greenstein + 1.0,
+ (1.0 - greenstein) * (1.0 - greenstein),0));
+
+ mDomeFP->setProgramLocalParameter(0, osg::Vec4( mBrightness, mContrast, 0, 0));
+ }
+
+ osg::VertexProgram* GetLightScatterinVP() { return mLightScatterinVP.get(); }
+ osg::FragmentProgram* GetDomeFP() { return mDomeFP.get(); }
+
+private:
+
+ ///our vertex program pointer
+ osg::ref_ptr<osg::VertexProgram> mLightScatterinVP;
+ ///our fragment program pointer
+ osg::ref_ptr<osg::FragmentProgram> mDomeFP;
+
+ osg::Vec3 lambda;
+ osg::Vec3 lambda2;
+ osg::Vec3 lambda4;
+ float n; ///<Refractive index of air
+ float pn; ///<depolarization factor of air
+ float greenstein; ///<eccentricity value
+ float mBrightness; ///<scene brightness adjustment
+ float mContrast; ///<scene contrast adjustment
+ osg::Vec3 betaRay;
+ osg::Vec3 betaMie;
+
+ float ConcentrationFactor(float turbidity)
+ {
+ return (6.544 * turbidity - 6.51) * 1e-17; ///<more magic numbers
+ }
+
+};
+
+class MakeSkyDome
+ {
+ public:
+
+ MakeSkyDome(float radius, bool capEnabled = true);
+ ~MakeSkyDome();
+
+ osg::Geode* Compute();
+
+ protected:
+
+ private:
+ unsigned int GetNumLevels();
+ void SetCoordinatesAndColors();
+ void SetCapCoordinatesAndColors();
+ void CreateTriangleStrips();
+ osg::StateSet* CreateStateSet() const;
+
+ float mRadius;
+ osg::Geometry* mGeom;
+ osg::Vec3Array* mCoordArray;
+ osg::Vec4Array* mColorArray;
+ std::vector<float> mLevelHeight;
+ std::vector<osg::Vec3> mCCArray;
+ bool theCapEnabled;
+
+ static const unsigned int VERTS_IN_CIRCUM;
+ };
+const unsigned int MakeSkyDome::VERTS_IN_CIRCUM = 19;
+
+////////////////////////////////////////////////////////////////////////////////
+MakeSkyDome::MakeSkyDome(float radius, bool capEnabled)
+: mRadius(radius)
+, mGeom(new osg::Geometry()),
+theCapEnabled(capEnabled)
+{
+ mLevelHeight.push_back(-9.0f);
+ mLevelHeight.push_back(-9.0f);
+ mLevelHeight.push_back(0.0f);
+ mLevelHeight.push_back(7.2f);
+ mLevelHeight.push_back(15.0f);
+ mLevelHeight.push_back(90.0f);
+
+ mCCArray.push_back(osg::Vec3(0.15f, 0.25f, 0.1f));
+ mCCArray.push_back(osg::Vec3(0.6f, 0.6f, 0.7f));
+ mCCArray.push_back(osg::Vec3(0.4f, 0.4f, 0.7f));
+ mCCArray.push_back(osg::Vec3(0.2f, 0.2f, 0.6f));
+ mCCArray.push_back(osg::Vec3(0.1f, 0.1f, 0.6f));
+ mCCArray.push_back(osg::Vec3(0.1f, 0.1f, 0.7f));
+
+ mCoordArray = new osg::Vec3Array(VERTS_IN_CIRCUM * mLevelHeight.size());
+ mColorArray = new osg::Vec4Array(VERTS_IN_CIRCUM * mLevelHeight.size());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+MakeSkyDome::~MakeSkyDome()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+osg::Geode* MakeSkyDome::Compute()
+{
+ SetCoordinatesAndColors();
+
+ CreateTriangleStrips();
+
+ mGeom->setVertexArray(mCoordArray);
+ mGeom->setColorArray(mColorArray);
+ mGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+
+ mGeom->setStateSet(CreateStateSet());
+ //mGeom->setUseVertexBufferObjects(true);
+// mGeom->setFastPathHint(false);
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(mGeom);
+ geode->setName("Sky");
+
+ return geode;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+unsigned int MakeSkyDome::GetNumLevels()
+{
+ return (mLevelHeight.size() - (theCapEnabled? 0: 1));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void MakeSkyDome::SetCoordinatesAndColors()
+{
+ unsigned int ci = theCapEnabled?VERTS_IN_CIRCUM:0;
+
+ // Set dome coordinates & colors
+ for(unsigned int i = theCapEnabled ? 1: 0; i < GetNumLevels(); i++)
+ {
+ for(unsigned int j = 0; j < VERTS_IN_CIRCUM; j++)
+ {
+ float alpha = osg::DegreesToRadians(mLevelHeight[i+(theCapEnabled ? 0: 1)]);
+ float theta = osg::DegreesToRadians((float)(j * 20));
+
+ float x = mRadius * cos(alpha) * cos(theta);
+ float y = mRadius * cos(alpha) * -sin( theta );
+ float z = mRadius * sin(alpha);
+
+ assert(ci < mCoordArray->size());
+ (*mCoordArray)[ci].set(x,y,z);
+
+ assert(ci < mColorArray->size());
+ assert(i < mCCArray.size());
+ (*mColorArray)[ci].set(mCCArray[i].x(), mCCArray[i].y(), mCCArray[i].z(), 1.f);
+
+ ci++;
+ }
+ }
+
+ SetCapCoordinatesAndColors();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void MakeSkyDome::SetCapCoordinatesAndColors()
+{
+ if(theCapEnabled)
+ {
+ osg::Vec3 capCenter(0.0f, 0.0f, mRadius * osg::DegreesToRadians(sin(mLevelHeight[0])));
+
+ for(unsigned int j = 0; j < VERTS_IN_CIRCUM; j++)
+ {
+ (*mCoordArray)[j] = capCenter;
+
+ assert(j < mColorArray->size());
+ (*mColorArray)[j].set(mCCArray.back().x(), mCCArray.back().y(), mCCArray.back().z(), 1.0f);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void MakeSkyDome::CreateTriangleStrips()
+{
+ for(unsigned int i = 0; i < GetNumLevels() - 1; i++)
+ {
+ osg::DrawElementsUShort* drawElements = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP);
+ drawElements->reserve(38);
+
+ for(unsigned j = 0; j < VERTS_IN_CIRCUM; j++)
+ {
+ drawElements->push_back((i + 1) * VERTS_IN_CIRCUM + j);
+ drawElements->push_back((i + 0) * VERTS_IN_CIRCUM + j);
+ }
+
+ mGeom->addPrimitiveSet(drawElements);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+osg::StateSet* MakeSkyDome::CreateStateSet() const
+{
+ osg::StateSet *dstate = new osg::StateSet;
+
+ dstate->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+ dstate->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
+
+ // clear the depth to the far plane.
+ osg::Depth* depth = new osg::Depth(osg::Depth::ALWAYS);
+ depth->setWriteMask(false);
+ dstate->setAttributeAndModes(depth,osg::StateAttribute::ON);
+ dstate->setMode(GL_FOG, osg::StateAttribute::OFF);
+ dstate->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ dstate->setRenderBinDetails(-2,"RenderBin");
+
+ return dstate;
+}
+#if 0
+static double fade_coefficient(double currentAltitude,
+ double refAltitude)
+{
+ return exp( - currentAltitude / refAltitude );
+}
+#endif
+static void fade_to_black(osg::Vec3 sky_color[],
+ double currentAltitude,
+ double refAltitude,
+ int count)
+{
+ double d = mkUtils::fadeCoefficient(currentAltitude, refAltitude);
+ d = ossim::clamp(d, 0.0, 1.0);
+ for(int i = 0; i < count ; i++)
+ {
+ sky_color[i] *= d;
+ }
+}
+static double fade_to_black(double curretValue,
+ double currentAltitude,
+ double refAltitude)
+{
+ double d = mkUtils::fadeCoefficient(currentAltitude, refAltitude);
+ d = ossim::clamp(d, 0.0, 1.0);
+ return curretValue*d;
+}
+
+class SkyDome : public EnvEffect
+{
+public:
+ SkyDome(const std::string& name = "SkyDome", bool createCapGeometry = true, float radius = 6000.0f)
+ :mEnableCap(createCapGeometry),
+ theMaxAltitude(80000)
+ {
+ SetOSGNode(new osg::Group());
+ mBaseColor.set(0.5f, 0.5f, 0.2f);
+ Config(radius);
+ }
+protected:
+ virtual ~SkyDome()
+ {
+
+ }
+
+public:
+ ///sets the base color
+ void SetBaseColor(const osg::Vec3& color)
+ {
+ osg::Geometry* geom = mGeode->getDrawable(0)->asGeometry();
+ osg::Array* array = geom->getColorArray();
+ if (array && array->getType() == osg::Array::Vec4ArrayType)
+ {
+ mBaseColor.set(color);
+
+ osg::Vec4Array* color = static_cast<osg::Vec4Array*>(array);
+ unsigned int limit = mEnableCap ? 38: 19;
+
+ for (unsigned int i=0; i<limit; i++)
+ {
+ assert(i<color->size());
+ (*color)[i].set(mBaseColor[0], mBaseColor[1], mBaseColor[2], 1.f);
+ }
+ geom->dirtyDisplayList();
+ }
+
+ }
+
+ ///gets the base color
+ void GetBaseColor(osg::Vec3& color) const { color.set(mBaseColor); }
+
+ bool GetCapEnabled() const { return mEnableCap; }
+
+ ///the virtual paint function
+ /** 0 degrees = horizon
+ * 90 degrees = high noon
+ * - degrees = below horizon
+ */
+ virtual void Repaint(const osg::Vec3& skyColor,
+ const osg::Vec3& fogColor,
+ double sunAngle,
+ double sunAzimuth,
+ double visibility,
+ double altitude = 0.0)
+ {
+ outer_param.set(0.0, 0.0, 0.0);
+ middle_param.set(0.0, 0.0, 0.0);
+
+ outer_diff.set(0.0, 0.0, 0.0);
+ middle_diff.set(0.0, 0.0, 0.0);
+
+ // Check for sunrise/sunset condition
+ if(IsSunsetOrSunrise(sunAngle))
+ {
+ // 0.0 - 0.4
+ outer_param.set((10.0 - std::abs(sunAngle)) / 20.0,
+ (10.0 - std::abs(sunAngle)) / 40.0,
+ -(10.0 - std::abs(sunAngle)) / 30.0);
+
+ middle_param.set((10.0 - std::abs(sunAngle)) / 40.0,
+ (10.0 - std::abs(sunAngle)) / 80.0,
+ 0.0);
+
+ outer_diff = outer_param / 9.0;
+
+ middle_diff = middle_param / 9.0;
+ }
+
+ outer_amt.set(outer_param);
+ middle_amt.set(middle_param);
+
+ // First, recaclulate the basic colors
+
+ CalcNewColors(visibility, skyColor, fogColor, altitude);
+
+ AssignColors();
+ }
+ void setMaxAltitude(double maxAltitude)
+ {
+ theMaxAltitude = maxAltitude;
+ }
+private:
+
+
+ /// Build the sky dome
+ void Config(float radius)
+ {
+ osg::Group* group = new osg::Group();
+
+ mGeode = MakeSkyDome(radius, mEnableCap).Compute();
+ GetOSGNode()->asGroup()->addChild(mGeode.get());
+ }
+ bool IsSunsetOrSunrise(double sunAngle) const
+ {
+ return ((sunAngle > -10.0) && (sunAngle < 10.0));
+ }
+ osg::Vec3 CalcCenterColors(double vis_factor,
+ const osg::Vec3& skyColor,
+ const osg::Vec3& fogColor) const
+ {
+ osg::Vec3 center_color;
+
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ const osg::Vec3::value_type diff = skyColor[j] - fogColor[j];
+ center_color[j] = skyColor[j] - diff * (1.0 - vis_factor);
+ }
+
+ return center_color;
+
+ }
+
+ void CalcNewColors(double visibility, const osg::Vec3& skyColor,
+ const osg::Vec3& fogColor,
+ double altitude = 0.0)
+ {
+ center_color = CalcCenterColors(GetVisibilityFactor(visibility), skyColor, fogColor);
+
+ for (unsigned int i = 0; i < 9; i++)
+ {
+ SetUpperMiddleLowerColors(skyColor, fogColor, i, visibility, altitude);
+
+ outer_amt -= outer_diff;
+ middle_amt -= middle_diff;
+ }
+
+ outer_amt.set(0.0, 0.0, 0.0);
+ middle_amt.set(0.0, 0.0, 0.0);
+
+ for (unsigned int i = 9; i < 19; i++)
+ {
+ SetUpperMiddleLowerColors(skyColor, fogColor, i, visibility, altitude);
+
+ outer_amt += outer_diff;
+ middle_amt += middle_diff;
+ }
+
+ for (unsigned int i = 0; i < 19; i++)
+ {
+ bottom_color[i] = fogColor;
+ }
+ }
+
+
+ double CalcCVF(double visibility) const
+ {
+ return ossim::clamp(visibility, 0.0, 20000.0);
+ }
+
+ void SetUpperMiddleLowerColors(const osg::Vec3& skyColor, const osg::Vec3& fogColor,
+ unsigned int i, double visibility, double altitude=0.0 )
+ {
+ const double cvf = CalcCVF(visibility);
+
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ const osg::Vec3::value_type diff = skyColor[j] - fogColor[j];
+
+ upper_color[i][j] = skyColor[j] - diff *
+ (1.0 - GetVisibilityFactor(visibility) * (0.7 + 0.3 * cvf/20000.f));
+
+ middle_color[i][j] = skyColor[j] - diff *
+ (1.0 - GetVisibilityFactor(visibility) * (0.1 + 0.85 * cvf/20000.f))
+ + middle_amt[j];
+
+ lower_color[i][j] = fogColor[j] + outer_amt[j];
+
+
+ upper_color[i][j] = ossim::clamp(upper_color[i][j], 0.f, 1.f);
+ middle_color[i][j] = ossim::clamp(middle_color[i][j], 0.f, 1.f);
+ lower_color[i][j] = ossim::clamp(lower_color[i][j], 0.f, 1.f);
+
+
+ }
+ //fade_to_black(&(*dome_cl)[0], asl * center_elev, 1);
+ fade_to_black(&upper_color[i], altitude, theMaxAltitude, 1);
+ fade_to_black(&middle_color[i], altitude, theMaxAltitude, 1);
+ fade_to_black(&lower_color[i], altitude, theMaxAltitude, 1);
+ }
+
+ void AssignColors() const
+ {
+ osg::Geometry* geom = mGeode->getDrawable(0)->asGeometry();
+ osg::Array* array = geom->getColorArray();
+ if (array && array->getType()==osg::Array::Vec4ArrayType)
+ {
+ osg::Vec4Array* color = dynamic_cast<osg::Vec4Array*>(array);
+ // Set cap color
+ if(mEnableCap)
+ {
+ for (unsigned int i = 0; i < 19; i++)
+ {
+ (*color)[i].set(bottom_color[i][0], bottom_color[i][1], bottom_color[i][2], 1.0);
+ }
+ }
+
+ // Set dome colors
+ unsigned int c = mEnableCap?19:0;
+ for(unsigned int i = 0; i < 19; i++)
+ {
+ (*color)[c].set(bottom_color[i][0], bottom_color[i][1], bottom_color[i][2], 1.0);
+ (*color)[c+19].set(lower_color[i][0], lower_color[i][1], lower_color[i][2], 1.0);
+ (*color)[c+19+19].set(middle_color[i][0], middle_color[i][1], middle_color[i][2], 1.0);
+ (*color)[c+19+19+19].set(upper_color[i][0], upper_color[i][1], upper_color[i][2], 1.0);
+ (*color)[c+19+19+19+19].set(center_color[0], center_color[1], center_color[2], 1.0);
+ c++;
+ }
+ geom->dirtyDisplayList();
+ }
+ }
+ double GetVisibilityFactor(double visibility) const
+ {
+ if (visibility < 3000.0)
+ {
+ double vis_factor = (visibility - 1000.0) / 2000.0;
+
+ ossim::clamp(vis_factor, 0.0, 1.0);
+ return vis_factor;
+ }
+
+ return 1.0;
+
+ }
+ osg::ref_ptr<osg::Geode> mGeode;
+ osg::ref_ptr<MoveEarthySkyWithEyePointTransformAzimuth> mXform;
+
+ bool mEnableCap;
+ osg::Vec3 mBaseColor;
+ osg::Vec3 outer_param, outer_amt, outer_diff;
+ osg::Vec3 middle_param, middle_amt, middle_diff;
+ osg::Vec3 center_color;
+ osg::Vec3 upper_color[19];
+ osg::Vec3 middle_color[19];
+ osg::Vec3 lower_color[19];
+ osg::Vec3 bottom_color[19];
+ osg::ref_ptr<osg::Group> theOsgNode;
+ ossim_float64 theMaxAltitude;
+};
+
+class ossimPlanetEphemeris::EphemerisData
+{
+public:
+ typedef std::vector<osg::ref_ptr<ossimPlanetCloudLayer> > CloudLayers;
+ ~EphemerisData()
+ {
+ theLayer = 0;
+ }
+ EphemerisData(ossimPlanetEphemeris* layer,
+ ossim_uint64 membersBitMap);
+ void setMembers(ossim_uint64 membersBitMap);
+ void traverse(osg::NodeVisitor& nv);
+ void updatePositions(osg::NodeVisitor& nv);
+ void setMoonLightIndex(ossim_uint32 idxNumber)
+ {
+ theMoonLightIdx = idxNumber;
+ if(theMoonLightSource.valid())
+ {
+ theMoonLightSource->getLight()->setLightNum(theMoonLightIdx);
+ }
+ }
+ ossim_uint32 moonLightIndex()const
+ {
+ return theMoonLightIdx;
+ }
+ void setSunLightIndex(ossim_uint32 idxNumber)
+ {
+ theSunLightIdx = idxNumber;
+ if(theSunLightSource.valid())
+ {
+ theSunLightSource->getLight()->setLightNum(theSunLightIdx);
+ }
+ }
+ ossim_uint32 sunLightIndex()const
+ {
+ return theSunLightIdx;
+ }
+ ossim_uint64 members()const
+ {
+ return theMembers;
+ }
+ void setDate(const ossimLocalTm& date)
+ {
+ theDate = date;
+ }
+ const ossimLocalTm& date()const
+ {
+ return theDate;
+ }
+ void setAutoUpdateToCurrentTimeFlag(bool flag)
+ {
+ theAutoUpdateCurrenTimeFlag = flag;
+ }
+ bool autoUpdateCurrentTimeFlag()const
+ {
+ return theAutoUpdateCurrenTimeFlag;
+ }
+ void setApplySimulationTimeOffsetFlag(bool flag)
+ {
+ theApplySimulationTimeOffsetFlag = flag;
+ }
+ void setAdjustedVisibility(ossim_float64 vis)
+ {
+ double sqrt_m_log01 = sqrt(-log(0.01));
+ float density = sqrt_m_log01 / vis;
+
+ theFog->setDensity(density);
+ if(theLayer->model())
+ {
+ theFog->setEnd(vis/theLayer->model()->getNormalizationScale());
+ }
+ }
+ void setVisibility(ossim_float64 visibility)
+ {
+ theVisibility = visibility;
+ setAdjustedVisibility(visibility);
+ }
+ double getVisibility()const
+ {
+ return theVisibility;
+ }
+ void setFogNear(ossim_float64 val)
+ {
+ theFogNear = val;
+ theFogNear = val;
+
+ if (theFogNear < 0.f)
+ {
+ theFogNear = 0.f;
+ }
+ if (theFogNear > theVisibility)
+ {
+ theFogNear = theVisibility;
+ }
+
+ if(theLayer->model())
+ {
+ theFog->setEnd(theVisibility/theLayer->model()->getNormalizationScale());
+ theFog->setStart(theFogNear/theLayer->model()->getNormalizationScale());///osg::WGS_84_RADIUS_EQUATOR);
+ }
+ }
+ void setFogFar(ossim_float64 val)
+ {
+ theFog->setEnd(val);///osg::WGS_84_RADIUS_EQUATOR);
+ }
+ void setFogDensity(ossim_float64 val)
+ {
+ theFog->setDensity(val);
+ }
+ void setFogMode(FogMode mode)
+ {
+ theFogMode = mode;
+ osg::Fog::Mode fm;
+ short attr = osg::StateAttribute::OFF;
+
+ switch (mode)
+ {
+ case ossimPlanetEphemeris::LINEAR: fm = osg::Fog::LINEAR; break;
+ case ossimPlanetEphemeris::EXP: fm = osg::Fog::EXP; break;
+ case ossimPlanetEphemeris::EXP2: fm = osg::Fog::EXP2; break;
+#if 0
+ case ossimPlanetEphemer::ADV:
+ {
+ fm = osg::Fog::LINEAR;
+ if (GetFogEnable()) { attr = osg::StateAttribute::ON; }
+ else { attr = osg::StateAttribute::OFF; }
+ }
+#endif
+ break;
+ default: fm = osg::Fog::LINEAR; break;
+ }
+
+ theFog->setMode(fm);
+ }
+ void updateSunLight()
+ {
+ double coefficient = mkUtils::fadeCoefficient(theEyeLlh[2], theMaxAltitudeToDoSunriseSunsetColorAdjustment);
+ coefficient = ossim::clamp(coefficient, 0.0, 1.0);
+ if(!theUseFadingFlagForSunriseSunsetCalculation)
+ {
+ if(theEyeLlh[2] > theMaxAltitudeToDoSunriseSunsetColorAdjustment)
+ {
+ coefficient = 0.0;
+ }
+ else
+ {
+ coefficient = 1.0;
+ }
+ }
+ osg::Vec3d position = theSunXyz;
+ osg::Vec3d direction = -theSunXyz;
+ direction.normalize();
+ if(!theSunLightSource.valid())
+ {
+ return;
+ }
+ double red = theSunElevation * 0.5;
+ double green = theSunElevation * 0.25;
+ double blue = theSunElevation * 0.125;
+ red = ossim::clamp(red, 0.0, 1.0);
+ green = ossim::clamp(green, 0.0, 1.0);
+ blue = ossim::clamp(blue, 0.0, 1.0);
+ osg::Vec3 diff1(1.0, 1.0, 1.0);
+ osg::Vec3 amb1(.01, 0.01, 0.01);
+ osg::Vec3 amb2(red, green, blue);
+ osg::Vec3 diff2(red, green, blue);
+
+ // setup a calculated ambient based on sun elevation
+ //
+ red = (theSunElevation + 10.0) * 0.04;
+ green = (theSunElevation + 10.0) * 0.02;
+ blue = (theSunElevation + 10.0) * 0.01;
+ red = ossim::clamp(red, 0.01, 0.3);
+ green = ossim::clamp(green, 0.01, 0.3);
+ blue = ossim::clamp(blue, 0.01, 0.3);
+ amb2 = osg::Vec3d(red, green, blue);
+
+ // fade the colors together to the reference height
+ //
+ osg::Vec3 diff = diff2*(coefficient) + diff1*(1.0-coefficient);
+ osg::Vec3 amb = amb2*(coefficient) + amb1*(1.0-coefficient);
+ osg::Vec4 d(diff[0], diff[1], diff[2], 1.0);
+
+ osg::Vec4 a(amb[0], amb[1], amb[2], 1.0);
+ theSunColor = diff;
+ theSunLightSource->getLight()->setDiffuse(d);
+ theSunLightSource->getLight()->setSpecular(d);
+ theSunLightSource->getLight()->setAmbient(a);
+ theSunLightSource->getLight()->setPosition(osg::Vec4d(position, 0.0));
+ theSunLightSource->getLight()->setDirection(direction);
+
+ if(theSunLightCallback.valid())
+ {
+ (*theSunLightCallback)(theLayer,
+ theSunLightSource.get());
+ osg::Vec4d diff = theSunLightSource->getLight()->getDiffuse();
+ theSunColor = osg::Vec3d(diff[0], diff[1], diff[2]);
+ }
+
+
+ osg::Vec4 d2(diff1[0], diff1[1], diff1[2], 1.0);
+ osg::Vec4 a2(amb1[0], amb1[1], amb1[2], 1.0);
+
+ theSunLightSourceMoonPhase->getLight()->setDiffuse(d2);
+ theSunLightSourceMoonPhase->getLight()->setSpecular(d2);
+ theSunLightSourceMoonPhase->getLight()->setAmbient(a2);
+ theSunLightSourceMoonPhase->getLight()->setPosition(osg::Vec4d(position, 0.0));
+ theSunLightSourceMoonPhase->getLight()->setDirection(direction);
+ }
+ void updateMoonLight()
+ {
+ if(theMembers&ossimPlanetEphemeris::MOON_LIGHT)
+ {
+ osg::Vec3d position = theSunXyz;
+ osg::Vec3d direction = -theSunXyz;
+ direction.normalize();
+ osg::Vec3d sunxyz=theSunXyz, moonxyz = theMoonXyz;
+ sunxyz.normalize();
+ moonxyz.normalize();
+ // Part of the calculations are used from osgEpehermis code
+ //
+ const double angle = (sunxyz*moonxyz);
+ const double moonBrightness = ((angle) * -0.5 + 0.5);
+ const double moonlight = moonBrightness*.5;
+ // Make the final values a little bit blue, and always add in a tiny bit of ambient starlight
+ osg::Vec4 ambient(moonlight * 0.32 + 0.05, moonlight * 0.32 + 0.05, moonlight * 0.4 + 0.05, 1);
+ osg::Vec4 diffuse(moonlight * 0.8, moonlight * 0.8, moonlight, 1);
+ osg::Light &light = *(theMoonLightSource->getLight());
+ light.setAmbient( ambient );
+ light.setDiffuse( diffuse );
+ light.setSpecular( diffuse );
+
+ theMoonLightSource->getLight()->setPosition( osg::Vec4d(theMoonXyz,0.0) );
+ theMoonLightSource->getLight()->setDirection(-moonxyz);
+ if(theMoonLightCallback.valid())
+ {
+ (*theMoonLightCallback)(theLayer,
+ theMoonLightSource.get());
+ }
+ }
+ }
+ void updateEnvColors()
+ {
+ float skyBright = theSkyLightTable->Interpolate(theSunElevation);
+ theModSkyColor = theSkyColor * skyBright;
+
+ // Modify the fog color based on sky brightness
+ theModFogColor = theFogColor * skyBright;
+ }
+ void updateFogColor()
+ {
+ // Calculate the fog color in the direction of the sun for
+ // sunrise/sunset effects.
+ float red = (theModFogColor[0] + 2.f * theSunColor[0] * theSunColor[0]) / 3.f;
+ float green = (theModFogColor[1] + 2.f * theSunColor[1] * theSunColor[1]) / 3.f;
+ float blue = (theModFogColor[2] + 2.f * theSunColor[2]) / 3.f;
+
+ // interpolate between the sunrise/sunset color and the color
+ // at the opposite direction of this effect. Take in account
+ // the current visibility.
+ double vis = getVisibility();
+ const float MAX_VISIBILITY = 20000;
+
+ // Clamp visibility
+ if (vis > MAX_VISIBILITY)
+ {
+ vis = MAX_VISIBILITY;
+ }
+
+ double sunRotation = osg::DegreesToRadians(-95.0);
+ double heading = osg::DegreesToRadians(-95.0);
+
+ double rotation = -(sunRotation + osg::PI) - heading;
+
+ float inverseVis = 1.f - (MAX_VISIBILITY - vis) / MAX_VISIBILITY;
+ float sif = 0.5f - cos(osg::DegreesToRadians(theSunElevation) * 2.f) / 2.f + 0.000001f;
+
+ float rf1 = std::abs((rotation-osg::PI) / osg::PI); // difference between eyepoint heading and sun heading (rad)
+ float rf2 = inverseVis * pow(rf1 * rf1, 1.0f / sif);
+
+ float rf3 = 1.f - rf2;
+
+ theModFogColor[0] = rf3 * theModFogColor[0] + rf2 * red;
+ theModFogColor[1] = rf3 * theModFogColor[1] + rf2 * green;
+ theModFogColor[2] = rf3 * theModFogColor[2] + rf2 * blue;
+
+ // now apply the fog's color
+ theFog->setColor(osg::Vec4(theModFogColor[0], theModFogColor[1], theModFogColor[2], 1.f));
+ }
+ bool getFogEnableFlag()const
+ {
+ return theFogEnableFlag;
+ }
+ void setFogEnableFlag(bool enable)
+ {
+ theFogEnableFlag = enable;
+ if(theRootStateSet.valid())
+ {
+ short attr = osg::StateAttribute::ON;
+
+ if (enable)
+ {
+ attr = osg::StateAttribute::ON;
+ }
+ else
+ {
+ attr = osg::StateAttribute::OFF;
+ }
+
+ theRootStateSet->setAttributeAndModes(theFog.get(), attr);
+#if 0
+ if (GetFogMode() == Environment::ADV)
+ {
+ // if we're using ADV, then we turn on/off this shader which overrides
+ // the standard openGL fog
+ state->setAttributeAndModes(mSunlightShader->GetLightScatterinVP(), attr);
+ state->setAttributeAndModes(mSunlightShader->GetTerrainFP(), attr);
+
+ // if we're using a skyDome, turn on/off its shader
+ if (mSkyDome.valid())
+ {
+ state = mSkyDome.get()->GetOSGNode()->getOrCreateStateSet();
+ state->setAttributeAndModes(mSkyDomeShader->GetLightScatterinVP(), attr);
+ state->setAttributeAndModes(mSkyDomeShader->GetDomeFP(), attr);
+ }
+ }
+#endif
+ }
+ }
+ osg::Texture2D* createBillboardTexture(osg::Image* image)
+ {
+ osg::Texture2D* texture = 0;
+ if ( image )
+ {
+ texture = new osg::Texture2D( image );
+ texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
+ texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
+ texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ }
+
+ return texture;
+ }
+ ossimPlanetBillboardIcon* createPlanetBillBoard(double diameter,
+ const string& name,
+ const string& imageFile)
+ {
+ ossimPlanetBillboardIcon* result = new ossimPlanetBillboardIcon();
+ result->setName(name);
+ result->setGroundObjectSize(diameter);
+ if(!imageFile.empty())
+ {
+ osg::Image* image = osgDB::readImageFile( imageFile );
+ if ( image )
+ {
+ result->setIcon(createBillboardTexture(image));
+ }
+ }
+
+ return result;
+ }
+ void setNumberOfCloudLayers(ossim_uint32 numberOfLayers)
+ {
+ ossim_uint32 idx = 0;
+ if(theCloudLayers.size() == numberOfLayers) return; // nothing to do
+ if(numberOfLayers == 0)
+ {
+ theCloudLayers.clear();
+ return;
+ }
+ theCloudLayers.resize(numberOfLayers);
+ for(idx = 0; idx < numberOfLayers;++idx)
+ {
+ if(!theCloudLayers[idx].valid())
+ {
+ theCloudLayers[idx] = new ossimPlanetCloudLayer();
+ theCloudLayers[idx]->setModel(theLayer->theModel.get());
+ theCloudLayers[idx]->setCullingActive(false);
+ }
+ }
+ }
+ void removeClouds(ossim_uint32 idx, ossim_uint32 count)
+ {
+ if((idx < theCloudLayers.size())&&
+ (count != 0))
+ {
+ ossim_uint32 maxIdx = ossim::min(idx+count, (ossim_uint32)theCloudLayers.size());;
+ CloudLayers::iterator start = theCloudLayers.begin()+idx;
+ CloudLayers::iterator end = theCloudLayers.begin()+maxIdx;
+ theCloudLayers.erase(start, end);
+ }
+ }
+
+ ossimPlanetCloudLayer* cloudLayer(ossim_uint32 idx)
+ {
+ if(idx < theCloudLayers.size())
+ {
+ return theCloudLayers[idx].get();
+ }
+ return 0;
+ }
+ public:
+ class InterpTable : public osg::Referenced
+ {
+ public:
+ InterpTable()
+ {
+
+ }
+ ~InterpTable()
+ {
+
+ }
+ void addEntry(double ind, double dep)
+ {
+ theTable.insert(std::make_pair(ind, dep));
+ }
+ double Interpolate(double x) const
+ {
+ double result = 0.0;
+ if(theTable.size() == 0) return result;
+ IntensityTableType::const_iterator upper = theTable.lower_bound(x);
+ IntensityTableType::const_iterator lower = upper;
+ if(upper != theTable.end())
+ {
+ if(upper != theTable.begin())
+ {
+ --lower;
+ }
+ }
+ if(upper!=theTable.end())
+ {
+ double t = 0.0;
+ if(lower!=upper)
+ {
+ t = (x-lower->first)/(upper->first-lower->first);
+ result = lower->second + (upper->second-lower->second)*t;
+ }
+ else
+ {
+ result = lower->second;
+ }
+ }
+ else if(upper==theTable.end())
+ {
+ if(lower!=theTable.end())
+ {
+ result = lower->second;
+ }
+ }
+ return result;
+ }
+ const ossimPlanetEphemeris::IntensityTableType& table()const
+ {
+ return theTable;
+ }
+ void setTable(const ossimPlanetEphemeris::IntensityTableType& value)
+ {
+ theTable = value;
+ }
+ protected:
+ ossimPlanetEphemeris::IntensityTableType theTable;
+ };
+
+ osg::ref_ptr<InterpTable> theSkyLightTable;
+
+ ossimPlanetEphemeris* theLayer;
+ ossim_uint64 theMembers;
+ ossimLocalTm theDate;
+ gpstk::SunPosition theSunPosition;
+ gpstk::MoonPosition theMoonPosition;
+ osg::Vec3d theSunLlh;
+ osg::Vec3d theMoonLlh;
+ osg::Vec3d theSunXyz;
+ osg::Vec3d theMoonXyz;
+
+ gpstk::WGS84Ellipsoid theEllipsoidModel;
+ //gpstk::WGS84Geoid theGeoidModel;
+ ossim_uint32 theSunLightIdx;
+ ossim_uint32 theMoonLightIdx;
+ ossim_uint32 theAmbientLightIdx;
+ osg::Vec3d theEyeLlh;
+ osg::Vec3d theEyeXyz;
+ osg::ref_ptr<osg::LightSource> theSunLightSource;
+ osg::ref_ptr<osg::LightSource> theSunLightSourceMoonPhase;
+ osg::ref_ptr<osg::LightSource> theMoonLightSource;
+ osg::ref_ptr<osg::LightSource> theAmbientLightSource;
+
+ osg::ref_ptr<osg::Group> theLightGroup;
+ osg::ref_ptr<osg::MatrixTransform> theObjectGroup;
+ osg::ref_ptr<osg::Group> theMoonGroup;
+ osg::ref_ptr<osg::Group> theSunGroup;
+
+ osg::ref_ptr<osg::MatrixTransform> theSkyDomeTransform;
+ osg::ref_ptr<SkyDome> theSkyDome;
+
+ /**
+ * This is the root stateset used for light source definitions
+ */
+ osg::observer_ptr<osg::StateSet> theRootStateSet;
+ osg::observer_ptr<osg::Group> theRootStateSetGroup;
+
+ bool theAutoUpdateCurrenTimeFlag;
+ bool theApplySimulationTimeOffsetFlag;
+ bool theSettingsChangedFlag;
+
+ ossim_float64 theSunElevation;
+ ossim_float64 theSunAzimuth;
+ osg::Vec3d theGlobalAmbientColor;
+ osg::Vec3d theSunColor;
+ osg::ref_ptr<ossimPlanetEphemeris::LightingCallback> theSunLightCallback;
+ osg::ref_ptr<ossimPlanetEphemeris::LightingCallback> theMoonLightCallback;
+ osg::ref_ptr<ossimPlanetEphemeris::LightingCallback> theGlobalAmbientLightCallback;
+ osg::Vec3d theSkyColor;
+ osg::Vec3d theFogColor;
+ osg::Vec3d theModSkyColor;
+ osg::Vec3d theModFogColor;
+
+ ossim_float64 theVisibility;
+ osg::ref_ptr<osg::Fog> theFog;
+ ossim_float64 theFogNear;
+ ossimPlanetEphemeris::FogMode theFogMode;
+ bool theFogEnableFlag;
+
+ osg::ref_ptr<ossimPlanetPointModel> theSunPointModel;
+ osg::ref_ptr<ossimPlanetBillboardIcon> theSunBillboard;
+ osg::ref_ptr<ossimPlanetPointModel> theMoonPointModel;
+
+ osg::ref_ptr<osg::PositionAttitudeTransform> theMoonModel;
+ osg::ref_ptr<osg::PositionAttitudeTransform> theSunModel;
+ osg::ref_ptr<osg::Camera> theSkyDomeCamera;
+
+ ossim_float64 theMaximumAltitudeToShowDome;
+ ossim_float64 theMaximumAltitudeToShowFog;
+ ossim_float64 theMaxAltitudeToDoSunriseSunsetColorAdjustment;
+ bool theUseFadingFlagForSunriseSunsetCalculation;
+ ossim_int64 theFrameStamp;
+
+ CloudLayers theCloudLayers;
+};
+ossimPlanetEphemeris::EphemerisData::EphemerisData(ossimPlanetEphemeris* layer,
+ ossim_uint64 membersBitMap)
+:theLayer(layer),
+theSunLightIdx(0),
+theMoonLightIdx(1),
+theAmbientLightIdx(2),
+theAutoUpdateCurrenTimeFlag(false),
+theApplySimulationTimeOffsetFlag(false),
+theSettingsChangedFlag(false),
+theMaximumAltitudeToShowDome(40000),
+theMaximumAltitudeToShowFog(20000),
+theMaxAltitudeToDoSunriseSunsetColorAdjustment(20000),
+theUseFadingFlagForSunriseSunsetCalculation(true),
+theFrameStamp(-1)
+{
+ theFogNear = 1.0;
+ theRootStateSet = 0;
+ theRootStateSetGroup = 0;
+ theGlobalAmbientColor = osg::Vec3d(0.2,0.2,0.2);
+ theSkyLightTable = new InterpTable();
+ theObjectGroup = new osg::MatrixTransform;
+ theLightGroup = new osg::Group;
+ theMoonGroup = new osg::Group;
+ theSunGroup = new osg::Group;
+ theMoonLightSource = new osg::LightSource;
+ theSunLightSource = new osg::LightSource;
+ theSunLightSourceMoonPhase = new osg::LightSource;
+ theAmbientLightSource = new osg::LightSource;
+ theLightGroup->addChild(theSunLightSource.get());
+ theLightGroup->addChild(theMoonLightSource.get());
+ theLightGroup->addChild(theAmbientLightSource.get());
+ theLightGroup->setCullingActive(false);
+ theSunLightSource->getLight()->setLightNum(theSunLightIdx);
+ theSunLightSource->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theSunLightSourceMoonPhase->getLight()->setLightNum(theSunLightIdx);
+ theSunLightSourceMoonPhase->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theMoonLightSource->getLight()->setLightNum(theMoonLightIdx);
+ theMoonLightSource->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theAmbientLightSource->getLight()->setLightNum(theAmbientLightIdx);
+ theAmbientLightSource->setLocalStateSetModes(osg::StateAttribute::OFF);
+
+ theAmbientLightSource->getLight()->setDiffuse(osg::Vec4d(0.0,0.0,0.0,1.0));
+ theAmbientLightSource->getLight()->setSpecular(osg::Vec4d(0.0,0.0,0.0,1.0));
+ theAmbientLightSource->getLight()->setAmbient(osg::Vec4d(theGlobalAmbientColor[0],
+ theGlobalAmbientColor[1],
+ theGlobalAmbientColor[2], 1.0));
+ theSunPointModel = new ossimPlanetPointModel;
+ theMoonPointModel = new ossimPlanetPointModel;
+ theMoonModel = new osg::PositionAttitudeTransform;
+ theSunModel = new osg::PositionAttitudeTransform;
+
+ osg::Geode* geode = new osg::Geode();
+
+ osg::TessellationHints* hints = new osg::TessellationHints;
+ hints->setDetailRatio(2.0);
+
+ geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3d(0.0f,0.0f,0.0f), 1.0), hints));
+
+ geode->setCullingActive(false);
+
+ theMoonModel->addChild(geode);
+ theMoonModel->setScale(osg::Vec3d(1.0, 1.0, 1.0));
+ theMoonModel->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
+ theMoonModel->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ theSunModel->addChild(geode);
+ theSunModel->setScale(osg::Vec3d(1.0, 1.0, 1.0));
+ theSunModel->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+ theSunModel->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ theSkyDome = new SkyDome("SkyDome", false, .4);//osg::WGS_84_RADIUS_EQUATOR);
+ theSkyDome->setMaxAltitude(theMaximumAltitudeToShowDome);
+ theSkyDomeTransform = new osg::MatrixTransform;
+ theSkyDomeTransform->addChild(theSkyDome->GetOSGNode());
+ theSkyDomeTransform->setCullingActive(false);
+ setMembers(membersBitMap);
+ theSkyLightTable->addEntry(-90.0, 0.080);
+ theSkyLightTable->addEntry(-50.0, 0.080);
+ theSkyLightTable->addEntry(-40.0, 0.090);
+ theSkyLightTable->addEntry(-25.0, 0.090);
+ theSkyLightTable->addEntry(-20.0, 0.110);
+ theSkyLightTable->addEntry(-15.0, 0.120);
+ theSkyLightTable->addEntry(-10.0, 0.200);
+ theSkyLightTable->addEntry(-5.0, 0.350);
+ theSkyLightTable->addEntry(0.0, 0.616);
+ theSkyLightTable->addEntry(5.0, 0.806);
+ theSkyLightTable->addEntry(10.0, 0.895);
+ theSkyLightTable->addEntry(20.0, 0.962);
+ theSkyLightTable->addEntry(30.0, 0.989);
+ theSkyLightTable->addEntry(40.0, 0.997);
+ theSkyLightTable->addEntry(50.0, 1.0);
+ theSkyLightTable->addEntry(90.0, 1.0);
+
+ theSkyColor.set(0.39f, 0.50f, 0.74f);
+ theFogColor.set(0.84f, 0.87f, 1.f);
+
+ theSunColor.set(1.f, 1.f, 1.f);
+ theModFogColor.set(theFogColor);
+ theModSkyColor.set(theSkyColor);
+ theVisibility = 20000;
+ theFog = new osg::Fog();
+ theFog->setDensity(0.0);
+ theMoonGroup->addChild(theSunLightSourceMoonPhase.get());
+ theObjectGroup->setUpdateCallback(new ossimPlanetTraverseCallback());
+ theObjectGroup->setCullCallback(new ossimPlanetTraverseCallback());
+ theObjectGroup->addChild(theSkyDomeTransform.get());
+
+ theObjectGroup->addChild(theMoonGroup.get());
+ theObjectGroup->addChild(theSunGroup.get());
+
+ setFogMode(ossimPlanetEphemeris::LINEAR);
+
+}
+
+void ossimPlanetEphemeris::EphemerisData::setMembers(ossim_uint64 membersBitMap)
+{
+ theMembers = membersBitMap;
+ if(theMembers&ossimPlanetEphemeris::SUN_LIGHT)
+ {
+ theSunLightSource->setLocalStateSetModes(osg::StateAttribute::ON);
+ theSunLightSource->getLight()->setLightNum(theSunLightIdx);
+ theSunLightSource->setNodeMask(0xffffffff);
+
+ theSunLightSourceMoonPhase->setLocalStateSetModes(osg::StateAttribute::ON);
+ theSunLightSourceMoonPhase->getLight()->setLightNum(theSunLightIdx);
+ theSunLightSourceMoonPhase->setNodeMask(0xffffffff);
+ }
+ else
+ {
+ theSunLightSource->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theSunLightSource->setNodeMask(0x0);
+ theSunLightSourceMoonPhase->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theSunLightSourceMoonPhase->setNodeMask(0x0);
+ }
+ if(theMembers&ossimPlanetEphemeris::MOON_LIGHT)
+ {
+ theMoonLightSource->getLight()->setLightNum(theMoonLightIdx);
+ theMoonLightSource->setLocalStateSetModes(osg::StateAttribute::ON);
+ theMoonLightSource->setNodeMask(0xffffffff);
+ }
+ else
+ {
+ theMoonLightSource->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theMoonLightSource->setNodeMask(0x0);
+ }
+ if(theMembers&ossimPlanetEphemeris::SKY)
+ {
+ theSkyDome->GetOSGNode()->setNodeMask(0xffffffff);
+ }
+ else
+ {
+ theSkyDome->GetOSGNode()->setNodeMask(0x0);
+ }
+
+
+ if(theMembers&ossimPlanetEphemeris::AMBIENT_LIGHT)
+ {
+ theAmbientLightSource->getLight()->setLightNum(theAmbientLightIdx);
+ theAmbientLightSource->setLocalStateSetModes(osg::StateAttribute::ON);
+ theAmbientLightSource->setNodeMask(0xffffffff);
+ }
+ else
+ {
+ theAmbientLightSource->setLocalStateSetModes(osg::StateAttribute::OFF);
+ theAmbientLightSource->setNodeMask(0x0);
+ }
+
+ theMoonGroup->removeChild(theMoonModel.get());
+
+ if(theMembers&ossimPlanetEphemeris::MOON)
+ {
+ theMoonGroup->addChild(theMoonModel.get());
+ }
+
+ theSunGroup->removeChild(theSunModel.get());
+ if(theMembers&ossimPlanetEphemeris::SUN)
+ {
+ theSunGroup->addChild(theSunModel.get());
+ }
+
+ if(theMembers&ossimPlanetEphemeris::FOG)
+ {
+ setFogEnableFlag(true);
+ }
+ else
+ {
+ setFogEnableFlag(false);
+ }
+ if(theRootStateSet.valid())
+ {
+ if(theMembers&ossimPlanetEphemeris::MOON_LIGHT)
+ {
+ theMoonLightSource->setStateSetModes(*theRootStateSet,osg::StateAttribute::ON);
+ }
+ else
+ {
+ theMoonLightSource->setStateSetModes(*theRootStateSet,osg::StateAttribute::OFF);
+ }
+ if(theMembers&ossimPlanetEphemeris::SUN_LIGHT)
+ {
+ theSunLightSource->setStateSetModes(*theRootStateSet,osg::StateAttribute::ON);
+ theSunLightSourceMoonPhase->setStateSetModes(*theRootStateSet,osg::StateAttribute::ON);
+ }
+ else
+ {
+ theSunLightSource->setStateSetModes(*theRootStateSet,osg::StateAttribute::OFF);
+ theSunLightSourceMoonPhase->setStateSetModes(*theRootStateSet,osg::StateAttribute::OFF);
+ }
+
+ if(theMembers&ossimPlanetEphemeris::AMBIENT_LIGHT)
+ {
+ theAmbientLightSource->setStateSetModes(*theRootStateSet,osg::StateAttribute::ON);
+ }
+ else
+ {
+ theAmbientLightSource->setStateSetModes(*theRootStateSet,osg::StateAttribute::OFF);
+ }
+ }
+
+ theLayer->setRedrawFlag(true);
+}
+
+void ossimPlanetEphemeris::EphemerisData::traverse(osg::NodeVisitor& nv)
+{
+ if(dynamic_cast<osgUtil::IntersectVisitor*> (&nv) ||
+ dynamic_cast<osgUtil::IntersectionVisitor*> (&nv))
+ {
+ return;
+ }
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ break;
+ }
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+
+ bool updatePositionFlag = true;
+
+ if(nv.getFrameStamp())
+ {
+ if(theFrameStamp == nv.getFrameStamp()->getFrameNumber())
+ {
+ updatePositionFlag = false;
+ }
+ theFrameStamp = nv.getFrameStamp()->getFrameNumber();
+ }
+ updatePositions(nv);
+ break;
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ static bool slaveAdded = false;
+ osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
+ if(ev)
+ {
+ ossimPlanetViewer* viewer = dynamic_cast<ossimPlanetViewer*>(ev->getActionAdapter());
+ if(viewer&&viewer->currentCamera())
+ {
+ theEyeLlh[0] = viewer->currentCamera()->lat();
+ theEyeLlh[1] = viewer->currentCamera()->lon();
+ theEyeLlh[2] = viewer->currentCamera()->altitude();
+ }
+ if(theSkyDomeCamera.valid())
+ {
+ theSkyDomeCamera->setNearFarRatio(.0001);
+ }
+#if 1
+ if(theEyeLlh[2] > theMaximumAltitudeToShowFog)
+ {
+ if(theRootStateSet.valid()&&getFogEnableFlag())
+ {
+ if(theRootStateSet->getMode(GL_FOG) == osg::StateAttribute::ON)
+ {
+ theRootStateSet->setAttributeAndModes(theFog.get(), osg::StateAttribute::OFF);
+ }
+ }
+ }
+ else
+ {
+ if(theRootStateSet.valid()&&getFogEnableFlag())
+ {
+ if(theRootStateSet->getMode(GL_FOG) == osg::StateAttribute::OFF)
+ {
+ theRootStateSet->setAttributeAndModes(theFog.get(), osg::StateAttribute::ON);
+ }
+ }
+ }
+#endif
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ if(!theSkyDomeCamera.valid())
+ {
+ theObjectGroup->accept(nv);
+ }
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theCloudLayers.size();++idx)
+ {
+ if(theCloudLayers[idx].valid())
+ {
+ theCloudLayers[idx]->accept(nv);
+ }
+ }
+ return;
+}
+
+void ossimPlanetEphemeris::EphemerisData::updatePositions(osg::NodeVisitor& nv)
+{
+ if(!theLayer||!theLayer->model()) return;
+
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = theLayer->model();
+
+ if(theAutoUpdateCurrenTimeFlag)
+ {
+ theDate.now();
+ theLayer->setRedrawFlag(true);
+ }
+ ossimLocalTm adjustedDate(theDate);
+ if(theApplySimulationTimeOffsetFlag&&nv.getFrameStamp())
+ {
+ double time = nv.getFrameStamp()->getSimulationTime();
+ adjustedDate.addSeconds(time);
+ theLayer->setRedrawFlag(true);
+ }
+ //gpstk::SystemTime now;
+ //ossimLocalTm gmt = adjustedDate;//.convertToGmt();
+ gpstk::UnixTime now(adjustedDate);
+ now.setTimeSystem(gpstk::TimeSystem::UTC);
+ //gpstk::DayTime now(gmt.getYear(),
+ // gmt.getMonth(),
+ // gmt.getDay(),
+ // gmt.getHour(),
+ // gmt.getMin(),
+ // gmt.getSec(),
+ // gpstk::DayTime::UTC);
+ gpstk::Position sunEcef;
+ sunEcef = theSunPosition.getPosition(now);
+
+//std::cout << "x: " << theEyeLlh[0] << std::endl;
+ gpstk::Position eyeLocation(theEyeLlh[0],
+ theEyeLlh[1],
+ theEyeLlh[2],
+ gpstk::Position::Geodetic,
+ &theEllipsoidModel,
+ gpstk::ReferenceFrame::WGS84);
+
+ gpstk::Position sunLlh = gpstk::Position(sunEcef,
+ gpstk::Position::Cartesian,
+ &theEllipsoidModel).asGeodetic(&theEllipsoidModel);
+
+ //gpstk::Position sunPosition(sunLlh.getLatitude(),
+ // sunLlh.getLongitude(),
+ // sunLlh.getAltitude(),
+ // gpstk::Position::Geodetic,
+ // &theEllipsoidModel);
+
+ theSunAzimuth = eyeLocation.azimuth(sunLlh);
+ theSunElevation = eyeLocation.elevation(sunLlh);
+
+ //std::cout << "Eye Position: " << eyeLocation << std::endl;
+ //std::cout << "Position: " << sunLlh << std::endl;
+ //std::cout << "Azimuth: " << theSunAzimuth << std::endl;
+ //std::cout << "Elevation: " << theSunElevation << std::endl;
+
+ theSunLlh = osg::Vec3d(sunLlh.getGeodeticLatitude(),
+ sunLlh.getLongitude(),
+ sunLlh.getAltitude());
+
+ gpstk::Position moonEcef;
+ moonEcef = theMoonPosition.getPosition(now);
+ gpstk::Position moonLlh = moonEcef.asGeodetic(&theEllipsoidModel);
+
+ theMoonLlh = osg::Vec3d(moonLlh.getGeodeticLatitude(),
+ moonLlh.getLongitude(),
+ moonLlh.getAltitude());
+
+ model->latLonHeightToXyz(theMoonLlh,
+ theMoonXyz);
+
+ osg::Matrixd m;
+ osg::Vec3d shiftedEye(theEyeLlh[0], theEyeLlh[1], 0.0);//theEyeLlh[2]);
+ theLayer->model()->lsrMatrix(shiftedEye, m, theSunAzimuth-90.0);
+ theLayer->model()->latLonHeightToXyz(theSunLlh,
+ theSunXyz);
+
+ theSkyDomeTransform->setMatrix(m);//*osg::Matrixd::Scale(.5,.5,.5));
+ osg::Vec3d eyexyzNorm;
+ theLayer->model()->latLonHeightToXyz(theEyeLlh, theEyeXyz);
+ eyexyzNorm = theEyeXyz;
+ eyexyzNorm.normalize();
+
+ theAmbientLightSource->getLight()->setDirection(-eyexyzNorm);
+ theAmbientLightSource->getLight()->setPosition(osg::Vec4d(theEyeXyz[0],
+ theEyeXyz[1],
+ theEyeXyz[2],
+ 0.0));
+
+ theSunModel->setPosition(theSunXyz);
+ theMoonModel->setPosition(theMoonXyz);
+#if 0
+ osg::Vec3d adjMoonXyz = theMoonXyz - theEyeXyz;
+ adjMoonXyz.normalize();
+ osg::Vec3d newMoonPos = theEyeXyz + adjMoonXyz*2;
+ osg::Vec3d newMoonLlh;
+ theLayer->theModel->xyzToLatLonHeight(newMoonPos, newMoonLlh);
+
+#endif
+
+ updateSunLight();
+ updateMoonLight();
+ updateEnvColors();
+ updateFogColor();
+
+ ossim_float64 vis = theVisibility;
+ osg::Vec3 fogColor = theModFogColor;
+ osg::Vec3 skyColor = theModSkyColor;
+ if (!getFogEnableFlag())
+ {
+ vis = 200000.f;
+ fogColor = theModSkyColor;
+ }
+ fade_to_black(&fogColor, theEyeLlh[2], theMaximumAltitudeToShowFog, 1);
+ fade_to_black(&skyColor, theEyeLlh[2], theMaximumAltitudeToShowDome, 1);
+ // if fog is enabled, use the modified fog color otherwise just use
+ // the modified sky color
+ theSkyDome->Repaint(skyColor,
+ fogColor,
+ theSunElevation,
+ theSunAzimuth,
+ vis,
+ theEyeLlh[2]);
+}
+
+ossimPlanetEphemeris::ossimPlanetEphemeris(ossim_uint64 membersBitMap)
+:theEphemerisData(new EphemerisData(this, membersBitMap))
+{
+
+}
+
+ossimPlanetEphemeris::~ossimPlanetEphemeris()
+{
+ if(theEphemerisData)
+ {
+ delete theEphemerisData;
+ theEphemerisData = 0;
+ }
+}
+
+void ossimPlanetEphemeris::setMembers(ossim_uint64 membersBitMap)
+{
+ if(theEphemerisData)
+ {
+ theEphemerisData->setMembers(membersBitMap);
+ }
+}
+
+ossim_uint64 ossimPlanetEphemeris::members()const
+{
+ return theEphemerisData->members();
+}
+
+void ossimPlanetEphemeris::setRoot(osg::Group* group)
+{
+ if(theEphemerisData->theRootStateSetGroup.valid())
+ {
+ theEphemerisData->theRootStateSetGroup->removeChild(theEphemerisData->theLightGroup.get());
+ }
+ theEphemerisData->theRootStateSetGroup = group;
+ if(group)
+ {
+ theEphemerisData->theRootStateSet = group->getOrCreateStateSet();
+ group->addChild(theEphemerisData->theLightGroup.get());
+ }
+}
+
+void ossimPlanetEphemeris::setMoonLightCallback(LightingCallback* callback)
+{
+ theEphemerisData->theMoonLightCallback = callback;
+}
+
+void ossimPlanetEphemeris::setMoonCullCallback(osg::NodeCallback* callback)
+{
+ theEphemerisData->theMoonGroup->setCullCallback(callback);
+}
+
+void ossimPlanetEphemeris::setMoonLightIndex(ossim_uint32 idxNumber)
+{
+ theEphemerisData->setMoonLightIndex(idxNumber);
+}
+
+ossim_uint32 ossimPlanetEphemeris::moonLightIndex()const
+{
+ return theEphemerisData->moonLightIndex();
+}
+
+osg::Vec3d ossimPlanetEphemeris::moonPositionXyz()const
+{
+ return theEphemerisData->theMoonXyz;
+}
+
+osg::Vec3d ossimPlanetEphemeris::moonPositionLatLonHeight()const
+{
+ return theEphemerisData->theMoonLlh;
+}
+
+void ossimPlanetEphemeris::setSunLightIndex(ossim_uint32 idxNumber)
+{
+ theEphemerisData->setSunLightIndex(idxNumber);
+}
+
+ossim_uint32 ossimPlanetEphemeris::sunLightIndex()const
+{
+ return theEphemerisData->sunLightIndex();
+}
+void ossimPlanetEphemeris::setSunLightCallback(LightingCallback* callback)
+{
+ theEphemerisData->theSunLightCallback = callback;
+}
+
+void ossimPlanetEphemeris::setSunCullCallback(osg::NodeCallback* callback)
+{
+ theEphemerisData->theSunGroup->setCullCallback(callback);
+}
+
+osg::Vec3d ossimPlanetEphemeris::sunPositionXyz()const
+{
+ return theEphemerisData->theSunXyz;
+}
+
+osg::Vec3d ossimPlanetEphemeris::sunPositionLatLonHeight()const
+{
+ return theEphemerisData->theSunLlh;
+}
+
+void ossimPlanetEphemeris::setDate(const ossimLocalTm& date)
+{
+ theEphemerisData->setDate(date);
+ theEphemerisData->setAutoUpdateToCurrentTimeFlag(false);
+}
+
+void ossimPlanetEphemeris::setAutoUpdateToCurrentTimeFlag(bool flag)
+{
+ theEphemerisData->setAutoUpdateToCurrentTimeFlag(flag);
+}
+
+void ossimPlanetEphemeris::setApplySimulationTimeOffsetFlag(bool flag)
+{
+ theEphemerisData->setApplySimulationTimeOffsetFlag(flag);
+ theEphemerisData->setAutoUpdateToCurrentTimeFlag(false);
+}
+
+
+void ossimPlanetEphemeris::traverse(osg::NodeVisitor& nv)
+{
+ if(!theEnableFlag) return;
+
+ theEphemerisData->traverse(nv);
+
+ ossimPlanetLayer::traverse(nv);
+}
+
+osg::Vec3d ossimPlanetEphemeris::eyePositionXyz()const
+{
+ return theEphemerisData->theEyeXyz;
+}
+
+osg::Vec3d ossimPlanetEphemeris::eyePositionLatLonHeight()const
+{
+ return theEphemerisData->theEyeLlh;
+}
+
+void ossimPlanetEphemeris::setCamera(osg::Camera* camera)
+{
+ if(theEphemerisData->theSkyDomeCamera.get() == camera) return;
+
+ if(theEphemerisData->theSkyDomeCamera.valid())
+ {
+ theEphemerisData->theSkyDomeCamera->removeChild(theEphemerisData->theObjectGroup.get());
+ }
+ theEphemerisData->theSkyDomeCamera = camera;
+ if(camera)
+ {
+ theEphemerisData->theSkyDomeCamera->addChild(theEphemerisData->theObjectGroup.get());
+ }
+}
+
+void ossimPlanetEphemeris::setVisibility(ossim_float64 visibility)
+{
+ theEphemerisData->setVisibility(visibility);
+}
+
+
+ossim_float64 ossimPlanetEphemeris::visibility()const
+{
+ return theEphemerisData->theVisibility;
+}
+
+osg::BoundingSphere ossimPlanetEphemeris::computeBound() const
+{
+ if(getNumChildren() == 0)
+ {
+ return osg::BoundingSphere(osg::Vec3(0.0,0.0,0.0),
+ 1.0);
+ }
+ return ossimPlanetLayer::computeBound();
+
+}
+
+void ossimPlanetEphemeris::setSunTextureFromFile(const ossimFilename& texture)
+{
+ osg::Image* image = osgDB::readImageFile( texture );
+ setSunTextureFromImage(image);
+}
+
+void ossimPlanetEphemeris::setSunTextureFromImage(osg::Image* texture)
+{
+ if ( texture )
+ {
+ osg::Texture2D* tex = new osg::Texture2D();
+ tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
+ tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
+ tex->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ tex->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ tex->setWrap(osg::Texture2D::WRAP_R, osg::Texture2D::CLAMP_TO_EDGE);
+
+ tex->setImage(texture);
+ theEphemerisData->theSunModel->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
+ }
+ else
+ {
+ theEphemerisData->theSunModel->getOrCreateStateSet()->setTextureAttributeAndModes(0, 0, osg::StateAttribute::OFF);
+ }
+}
+
+void ossimPlanetEphemeris::setMoonTextureFromFile(const ossimFilename& texture)
+{
+ osg::Image* image = osgDB::readImageFile( texture );
+ setMoonTextureFromImage(image);
+}
+
+void ossimPlanetEphemeris::setMoonScale(const osg::Vec3d& scale)
+{
+ theEphemerisData->theMoonModel->setScale(scale);
+}
+
+void ossimPlanetEphemeris::setSunScale(const osg::Vec3d& scale)
+{
+ theEphemerisData->theSunModel->setScale(scale);
+}
+
+void ossimPlanetEphemeris::setMoonTextureFromImage(osg::Image* texture)
+{
+ if ( texture )
+ {
+ osg::Texture2D* tex = new osg::Texture2D();
+ tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
+ tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
+ tex->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ tex->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ tex->setWrap(osg::Texture2D::WRAP_R, osg::Texture2D::CLAMP_TO_EDGE);
+
+ tex->setImage(texture);
+ theEphemerisData->theMoonModel->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
+ }
+ else
+ {
+ theEphemerisData->theMoonModel->getOrCreateStateSet()->setTextureAttributeAndModes(0, 0, osg::StateAttribute::OFF);
+ }
+}
+
+
+void ossimPlanetEphemeris::setSunMinMaxPixelSize(ossim_uint32 minPixelSize,
+ ossim_uint32 maxPixelSize)
+{
+
+ theEphemerisData->theSunBillboard->setMinPixelSize(minPixelSize);
+ theEphemerisData->theSunBillboard->setMaxPixelSize(maxPixelSize);
+}
+
+void ossimPlanetEphemeris::setMaximumAltitudeToShowDomeInMeters(ossim_float64 maxAltitude)
+{
+ theEphemerisData->theMaximumAltitudeToShowDome = maxAltitude;
+}
+
+void ossimPlanetEphemeris::setMaximumAltitudeToShowFogInMeters(ossim_float64 maxAltitude)
+{
+ theEphemerisData->theMaximumAltitudeToShowFog = maxAltitude;
+}
+void ossimPlanetEphemeris::setMaxAltitudeToDoSunriseSunsetColorAdjustment(ossim_float64 maxAltitude,
+ bool useFading)
+{
+ theEphemerisData->theMaxAltitudeToDoSunriseSunsetColorAdjustment = maxAltitude;
+ theEphemerisData->theUseFadingFlagForSunriseSunsetCalculation = useFading;
+}
+
+ossim_float64 ossimPlanetEphemeris::maxAltitudeToDoSunriseSunsetColorAdjustment()const
+{
+ return theEphemerisData->theMaxAltitudeToDoSunriseSunsetColorAdjustment;
+}
+
+
+void ossimPlanetEphemeris::setGlobalAmbientLight(const osg::Vec3d& ambient)
+{
+ theEphemerisData->theGlobalAmbientColor = ambient;
+ theEphemerisData->theAmbientLightSource->getLight()->setAmbient(osg::Vec4d(theEphemerisData->theGlobalAmbientColor[0],
+ theEphemerisData->theGlobalAmbientColor[1],
+ theEphemerisData->theGlobalAmbientColor[2], 1.0));
+}
+
+void ossimPlanetEphemeris::setGlobalAmbientLightIndex(ossim_uint32 idx)
+{
+ theEphemerisData->theAmbientLightIdx = idx;
+ theEphemerisData->theAmbientLightSource->getLight()->setLightNum(theEphemerisData->theAmbientLightIdx);
+}
+
+ossim_uint32 ossimPlanetEphemeris::globalAmbientLightIndex()const
+{
+ return theEphemerisData->theAmbientLightIdx;
+}
+
+void ossimPlanetEphemeris::setSkyColorAdjustmentTable(IntensityTableType& table)
+{
+ theEphemerisData->theSkyLightTable->setTable(table);
+}
+
+const ossimPlanetEphemeris::IntensityTableType* ossimPlanetEphemeris::skyColorAdjustmentTable()const
+{
+ return &theEphemerisData->theSkyLightTable->table();
+}
+
+void ossimPlanetEphemeris::setBaseSkyColor(const osg::Vec3d& color)
+{
+ theEphemerisData->theSkyColor = color;
+}
+osg::Vec3d ossimPlanetEphemeris::getBaseSkyColor()const
+{
+ return theEphemerisData->theSkyColor;
+}
+
+void ossimPlanetEphemeris::setBaseFogColor(const osg::Vec3d& color)
+{
+ theEphemerisData->theFogColor = color;
+}
+
+osg::Vec3d ossimPlanetEphemeris::getBaseFogColor()const
+{
+ return theEphemerisData->theFogColor;
+}
+
+void ossimPlanetEphemeris::setFogMode(FogMode mode)
+{
+ theEphemerisData->setFogMode(mode);
+}
+
+void ossimPlanetEphemeris::setFogNear(ossim_float64 value)
+{
+ theEphemerisData->setFogNear(value);///osg::WGS_84_RADIUS_EQUATOR);
+}
+void ossimPlanetEphemeris::setFogFar(ossim_float64 value)
+{
+ theEphemerisData->setFogFar(value);///osg::WGS_84_RADIUS_EQUATOR);
+}
+void ossimPlanetEphemeris::setFogDensity(ossim_float64 value)
+{
+ theEphemerisData->setFogDensity(value);
+}
+
+void ossimPlanetEphemeris::setFogEnableFlag(bool flag)
+{
+ theEphemerisData->setFogEnableFlag(flag);
+}
+void ossimPlanetEphemeris::setNumberOfCloudLayers(ossim_uint32 numberOfLayers)
+{
+ theEphemerisData->setNumberOfCloudLayers(numberOfLayers);
+}
+
+void ossimPlanetEphemeris::removeClouds(ossim_uint32 idx, ossim_uint32 count)
+{
+ theEphemerisData->removeClouds(idx, count);
+}
+
+ossimPlanetCloudLayer* ossimPlanetEphemeris::cloudLayer(ossim_uint32 idx)
+{
+ return theEphemerisData->cloudLayer(idx);
+}
+
+ossim_uint32 ossimPlanetEphemeris::numberOfCloudLayers()const
+{
+ return theEphemerisData->theCloudLayers.size();
+}
+
+void ossimPlanetEphemeris::createCloudPatch(ossim_uint32 cloudLayerIndex,
+ const osg::Vec3d& theCenterLatLonHeight,
+ ossim_float64 numberOfMeshSamples,
+ ossim_float64 patchSizeInDegrees,
+ ossim_uint64 seed,
+ ossim_float64 coverage,
+ ossim_float64 sharpness)
+{
+ if(cloudLayerIndex == numberOfCloudLayers())
+ {
+ setNumberOfCloudLayers(cloudLayerIndex+1);
+ }
+ osg::ref_ptr<ossimPlanetCloudLayer> layer = cloudLayer(cloudLayerIndex);
+ if(layer.valid())
+ {
+ layer->setGrid(new ossimPlanetCloudLayer::Patch(patchSizeInDegrees, patchSizeInDegrees));
+ layer->computeMesh(0.0, numberOfMeshSamples, numberOfMeshSamples, 0);
+ layer->updateTexture(seed, coverage, sharpness);
+ layer->moveToLocationLatLonAltitude(theCenterLatLonHeight);
+ }
+}
+
+void ossimPlanetEphemeris::createGlobalCloud(ossim_uint32 cloudLayerIndex,
+ ossim_float64 altitude,
+ ossim_float64 numberOfMeshSamples,
+ ossim_uint64 seed,
+ ossim_float64 coverage,
+ ossim_float64 sharpness)
+{
+ if(cloudLayerIndex == numberOfCloudLayers())
+ {
+ setNumberOfCloudLayers(cloudLayerIndex+1);
+ }
+ osg::ref_ptr<ossimPlanetCloudLayer> layer = cloudLayer(cloudLayerIndex);
+ if(layer.valid())
+ {
+ layer->computeMesh(altitude, numberOfMeshSamples, numberOfMeshSamples, 0);
+ layer->updateTexture(seed, coverage, sharpness);
+ }
+}
+
+#else
+#include <iostream>
+#include <ossimPlanet/ossimPlanetEphemeris.h>
+static void noossimPlanetEphemerisSupportMessage()
+{
+ static bool messageDisplayed = false;
+ if(!messageDisplayed)
+ {
+ messageDisplayed = true;
+ std::cout << "ossimPlanetEphemeris support disabled, please recompile with OSSIMPLANET_ENABLE_EPHEMERIS defined\n";
+ }
+}
+ossimPlanetEphemeris::ossimPlanetEphemeris(ossim_uint64 )
+:theEphemerisData(0)
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossimPlanetEphemeris::~ossimPlanetEphemeris()
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::traverse(osg::NodeVisitor& nv)
+{
+ noossimPlanetEphemerisSupportMessage();
+ ossimPlanetLayer::traverse(nv);
+}
+
+osg::Vec3d ossimPlanetEphemeris::eyePositionXyz()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+osg::Vec3d ossimPlanetEphemeris::eyePositionLatLonHeight()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+void ossimPlanetEphemeris::setMembers(ossim_uint64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossim_uint64 ossimPlanetEphemeris::members()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0;
+}
+
+void ossimPlanetEphemeris::setRoot(osg::Group* )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+
+void ossimPlanetEphemeris::setMoonLightIndex(ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossim_uint32 ossimPlanetEphemeris::moonLightIndex()const
+{
+ noossimPlanetEphemerisSupportMessage();
+
+ return 0;
+}
+
+void ossimPlanetEphemeris::setMoonLightCallback(LightingCallback* )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+osg::Vec3d ossimPlanetEphemeris::moonPositionXyz()const
+{
+ noossimPlanetEphemerisSupportMessage();
+
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+osg::Vec3d ossimPlanetEphemeris::moonPositionLatLonHeight()const
+{
+ noossimPlanetEphemerisSupportMessage();
+
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+
+void ossimPlanetEphemeris::setSunLightIndex(ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossim_uint32 ossimPlanetEphemeris::sunLightIndex()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0;
+}
+
+void ossimPlanetEphemeris::setSunLightCallback(LightingCallback* )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+osg::Vec3d ossimPlanetEphemeris::sunPositionXyz()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+osg::Vec3d ossimPlanetEphemeris::sunPositionLatLonHeight()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+void ossimPlanetEphemeris::setAutoUpdateSunColorFlag(bool )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setGlobalAmbientLightIndex(ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossim_uint32 ossimPlanetEphemeris::globalAmbientLightIndex()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0;
+}
+
+void ossimPlanetEphemeris::setGlobalAmbientLight(const osg::Vec3d& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setDate(const ossimLocalTm& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setAutoUpdateToCurrentTimeFlag(bool )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setApplySimulationTimeOffsetFlag(bool )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setCamera(osg::Camera* )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setVisibility(ossim_float64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossim_float64 ossimPlanetEphemeris::visibility()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0.0;
+}
+
+void ossimPlanetEphemeris::setSunTextureFromFile(const ossimFilename& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+void ossimPlanetEphemeris::setSunTextureFromImage(osg::Image* )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setMoonTextureFromFile(const ossimFilename& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+void ossimPlanetEphemeris::setMoonTextureFromImage(osg::Image* )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setMoonScale(const osg::Vec3d& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setSunScale(const osg::Vec3d& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setSunMinMaxPixelSize(ossim_uint32 ,
+ ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+
+void ossimPlanetEphemeris::setMaximumAltitudeToShowDomeInMeters(ossim_float64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+
+void ossimPlanetEphemeris::setMaximumAltitudeToShowFogInMeters(ossim_float64 /*maxAltitude*/)
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setMaxAltitudeToDoSunriseSunsetColorAdjustment(ossim_float64 /*maxAltitude*/,
+ bool /*useFading*/)
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+ossim_float64 ossimPlanetEphemeris::maxAltitudeToDoSunriseSunsetColorAdjustment()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0.0;
+}
+
+void ossimPlanetEphemeris::setSkyColorAdjustmentTable(IntensityTableType& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+const ossimPlanetEphemeris::IntensityTableType* ossimPlanetEphemeris::skyColorAdjustmentTable()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0;
+}
+
+void ossimPlanetEphemeris::setBaseSkyColor(const osg::Vec3d& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+osg::Vec3d ossimPlanetEphemeris::getBaseSkyColor()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+
+void ossimPlanetEphemeris::setBaseFogColor(const osg::Vec3d& )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+osg::Vec3d ossimPlanetEphemeris::getBaseFogColor()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return osg::Vec3d(0.0,0.0,0.0);
+}
+
+void ossimPlanetEphemeris::setFogMode(FogMode )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+void ossimPlanetEphemeris::setFogNear(ossim_float64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+
+}
+void ossimPlanetEphemeris::setFogFar(ossim_float64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+void ossimPlanetEphemeris::setFogDensity(ossim_float64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+void ossimPlanetEphemeris::setFogEnableFlag(bool )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::setNumberOfCloudLayers(ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+void ossimPlanetEphemeris::removeClouds(ossim_uint32 , ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+ossimPlanetCloudLayer* ossimPlanetEphemeris::cloudLayer(ossim_uint32 )
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0;
+}
+ossim_uint32 ossimPlanetEphemeris::numberOfCloudLayers()const
+{
+ noossimPlanetEphemerisSupportMessage();
+ return 0;
+}
+
+void ossimPlanetEphemeris::createCloudPatch(ossim_uint32 ,
+ const osg::Vec3d& ,
+ ossim_float64 ,
+ ossim_float64 ,
+ ossim_uint64 ,
+ ossim_float64 ,
+ ossim_float64 )
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+void ossimPlanetEphemeris::createGlobalCloud(ossim_uint32 cloudLayerIndex,
+ ossim_float64 altitude,
+ ossim_float64 numberOfMeshSamples,
+ ossim_uint64 seed,
+ ossim_float64 coverage,
+ ossim_float64 sharpness)
+{
+ noossimPlanetEphemerisSupportMessage();
+}
+
+osg::BoundingSphere ossimPlanetEphemeris::computeBound() const
+{
+ noossimPlanetEphemerisSupportMessage();
+ if(getNumChildren() == 0)
+ {
+ return osg::BoundingSphere(osg::Vec3(0.0,0.0,0.0),
+ 1.0);
+ }
+ return ossimPlanetLayer::computeBound();
+}
+
+#endif
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetFadeText.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetFadeText.cpp
new file mode 100644
index 0000000..d57eaba
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetFadeText.cpp
@@ -0,0 +1,471 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <iostream>
+#include <ossimPlanet/ossimPlanetFadeText.h>
+#include <osg/Notify>
+#include <osg/io_utils>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+#include <osgUtil/CullVisitor>
+#include <ossim/base/ossimCommon.h>
+
+// using namespace osgText;
+
+// struct ossimPlanetFadeTextData : public osg::Referenced
+// {
+// ossimPlanetFadeTextData(ossimPlanetFadeText* fadeText=0):
+// _fadeText(fadeText),
+// _visible(true) {}
+
+// bool operator < (const ossimPlanetFadeTextData& rhs) const
+// {
+// return _fadeText < rhs._fadeText;
+// }
+
+// double getNearestZ() const
+// {
+// double nearestZ = _vertices[0].z();
+// if (nearestZ < _vertices[1].z()) nearestZ = _vertices[1].z();
+// if (nearestZ < _vertices[2].z()) nearestZ = _vertices[2].z();
+// if (nearestZ < _vertices[3].z()) nearestZ = _vertices[3].z();
+
+// // osg::notify(osg::NOTICE)<<"getNearestZ()="<<_fadeText->getText().createUTF8EncodedString()<<" "<<nearestZ<<std::endl;
+
+// return nearestZ;
+// }
+
+// ossimPlanetFadeText* _fadeText;
+// osg::Vec3d _vertices[4];
+// bool _visible;
+// };
+
+// struct ossimPlanetFadeTextPolytopeData : public ossimPlanetFadeTextData, public osg::Polytope
+// {
+// ossimPlanetFadeTextPolytopeData(ossimPlanetFadeTextData& fadeTextData):
+// ossimPlanetFadeTextData(fadeTextData)
+// {
+// _referenceVertexList.push_back(_vertices[0]);
+// _referenceVertexList.push_back(_vertices[1]);
+// _referenceVertexList.push_back(_vertices[2]);
+// _referenceVertexList.push_back(_vertices[3]);
+// }
+
+// void addEdgePlane(const osg::Vec3& corner, const osg::Vec3& edge)
+// {
+// osg::Vec3 normal( edge.y(), -edge.x(), 0.0f);
+// normal.normalize();
+
+// add(osg::Plane(normal, corner));
+// }
+
+// void buildPolytope()
+// {
+// osg::Vec3d edge01 = _vertices[1] - _vertices[0];
+// osg::Vec3d edge12 = _vertices[2] - _vertices[1];
+// osg::Vec3d edge23 = _vertices[3] - _vertices[2];
+// osg::Vec3d edge30 = _vertices[0] - _vertices[3];
+
+// osg::Vec3d normalFrontFace = edge01 ^ edge12;
+// bool needToFlip = normalFrontFace.z()>0.0f;
+
+// normalFrontFace.normalize();
+// add(osg::Plane(normalFrontFace, _vertices[0]));
+
+// add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[0], _vertices[1]));
+// add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[1], _vertices[2]));
+// add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[2], _vertices[3]));
+// add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[3], _vertices[0]));
+
+// #if 0
+// osg::notify(osg::NOTICE)<<" normalFrontFace = "<<normalFrontFace<<std::endl;
+// osg::notify(osg::NOTICE)<<" edge01 = "<<edge01<<std::endl;
+// osg::notify(osg::NOTICE)<<" edge12 = "<<edge12<<std::endl;
+// osg::notify(osg::NOTICE)<<" edge23 = "<<edge23<<std::endl;
+// osg::notify(osg::NOTICE)<<" _vertices[0]= "<<_vertices[0]<<std::endl;
+// osg::notify(osg::NOTICE)<<" _vertices[1]= "<<_vertices[1]<<std::endl;
+// osg::notify(osg::NOTICE)<<" _vertices[2]= "<<_vertices[2]<<std::endl;
+// osg::notify(osg::NOTICE)<<" _vertices[3]= "<<_vertices[3]<<std::endl;
+// #endif
+
+// if (needToFlip) flip();
+
+// #if 0
+// osg::notify(osg::NOTICE)<<" plane 0 "<< _planeList[0]<<std::endl;
+// osg::notify(osg::NOTICE)<<" plane 1 "<< _planeList[1]<<std::endl;
+// osg::notify(osg::NOTICE)<<" plane 2 "<< _planeList[2]<<std::endl;
+// osg::notify(osg::NOTICE)<<" plane 3 "<< _planeList[3]<<std::endl;
+// osg::notify(osg::NOTICE)<<" plane 4 "<< _planeList[4]<<std::endl;
+// #endif
+
+// }
+
+// inline bool contains(const std::vector<osg::Vec3>& vertices)
+// {
+// for(std::vector<osg::Vec3>::const_iterator itr = vertices.begin();
+// itr != vertices.end();
+// ++itr)
+// {
+// if (osg::Polytope::contains(*itr))
+// {
+// return true;
+// }
+// }
+// return false;
+// }
+
+// };
+
+// struct ossimPlanetFadeTextUserData : public osg::Referenced
+// {
+// ossimPlanetFadeTextUserData():
+// _frameNumber(0) {}
+
+// typedef std::list<ossimPlanetFadeTextData> FadeTextList;
+// unsigned int _frameNumber;
+// FadeTextList _fadeTextInView;
+// };
+
+// struct ossimPlanetGlobalFadeText : public osg::Referenced
+// {
+// typedef std::set< osg::ref_ptr<ossimPlanetFadeTextUserData> > UserDataSet;
+// typedef std::set<ossimPlanetFadeText*> FadeTextSet;
+// typedef std::multimap<double, osg::ref_ptr<ossimPlanetFadeTextPolytopeData> > FadeTextPolytopeMap;
+// typedef std::map<osg::View*, UserDataSet> ViewUserDataMap;
+// typedef std::map<osg::View*, FadeTextSet > ViewFadeTextMap;
+
+// ossimPlanetGlobalFadeText():
+// _frameNumber(0xffffffff)
+// {
+// }
+
+
+// ossimPlanetFadeTextUserData* createNewFadeTextUserData(osg::View* view)
+// {
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+
+// ossimPlanetFadeTextUserData* userData = new ossimPlanetFadeTextUserData;
+
+// if (!userData)
+// {
+// osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<<std::endl;
+// return 0;
+// }
+
+// _viewMap[view].insert(userData);
+
+// return userData;
+// }
+
+
+// void update(unsigned int frameNumber)
+// {
+// _frameNumber = frameNumber;
+// for(ossimPlanetGlobalFadeText::ViewUserDataMap::iterator vitr = _viewMap.begin();
+// vitr != _viewMap.end();
+// ++vitr)
+// {
+// osg::View* view = vitr->first;
+
+// FadeTextSet& fadeTextSet = _viewFadeTextMap[view];
+// fadeTextSet.clear();
+
+// FadeTextPolytopeMap fadeTextPolytopeMap;
+
+// for(ossimPlanetGlobalFadeText::UserDataSet::iterator uitr = vitr->second.begin();
+// uitr != vitr->second.end();
+// ++uitr)
+// {
+// ossimPlanetFadeTextUserData* userData = uitr->get();
+
+// int frameDelta = frameNumber - userData->_frameNumber;
+// if (frameDelta<=1)
+// {
+// for(ossimPlanetFadeTextUserData::FadeTextList::iterator fitr = userData->_fadeTextInView.begin();
+// (fitr != userData->_fadeTextInView.end());
+// ++fitr)
+// {
+// ossimPlanetFadeTextData& fadeTextData = *fitr;
+// if (fadeTextSet.count(fadeTextData._fadeText)==0)
+// {
+// fadeTextSet.insert(fadeTextData._fadeText);
+// fadeTextPolytopeMap.insert(FadeTextPolytopeMap::value_type(
+// -fadeTextData.getNearestZ(), new ossimPlanetFadeTextPolytopeData(fadeTextData)));
+// }
+// }
+// }
+// }
+
+// #if 0
+// // for each FadeTexPoltopeData
+// // create polytopes
+// // test against all FTPD's later in the list
+// // test all control points on FTPD against each plane of the current polytope
+// // if all control points removed or outside then discard FTPD and make FT visible = false;
+
+// FadeTextPolytopeMap::iterator outer_itr = fadeTextPolytopeMap.begin();
+// while (outer_itr != fadeTextPolytopeMap.end())
+// {
+// FadeTextPolytopeMap::iterator inner_itr = outer_itr;
+// ++inner_itr;
+
+// if (inner_itr == fadeTextPolytopeMap.end()) break;
+
+// ossimPlanetFadeTextPolytopeData& outer_ftpm = *(outer_itr->second);
+// outer_ftpm.buildPolytope();
+
+// // osg::notify(osg::NOTICE)<<"Outer z "<<outer_ftpm.getNearestZ()<<std::endl;
+
+// while(inner_itr != fadeTextPolytopeMap.end())
+// {
+// ossimPlanetFadeTextPolytopeData& inner_ftpm = *(inner_itr->second);
+
+// // osg::notify(osg::NOTICE)<<"Inner z "<<inner_ftpm.getNearestZ()<<std::endl;
+
+// if (outer_ftpm.contains(inner_ftpm.getReferenceVertexList()))
+// {
+// FadeTextPolytopeMap::iterator erase_itr = inner_itr;
+// // move to next ftpm
+// ++inner_itr;
+
+// fadeTextSet.erase(inner_ftpm._fadeText);
+
+// // need to remove inner_ftpm as its occluded.
+// fadeTextPolytopeMap.erase(erase_itr);
+
+// }
+// else
+// {
+// // move to next ftpm
+// ++inner_itr;
+// }
+// }
+
+// ++outer_itr;
+
+// }
+// #endif
+// }
+// }
+
+// inline void updateIfRequired(unsigned int frameNumber)
+// {
+// if (_frameNumber!=frameNumber) update(frameNumber);
+// }
+
+// unsigned int _frameNumber;
+// OpenThreads::Mutex _mutex;
+// ViewUserDataMap _viewMap;
+// ViewFadeTextMap _viewFadeTextMap;
+// };
+
+// ossimPlanetGlobalFadeText* getGlobalFadeText()
+// {
+// static osg::ref_ptr<ossimPlanetGlobalFadeText> s_globalFadeText = new ossimPlanetGlobalFadeText;
+// return s_globalFadeText.get();
+// }
+struct ossimPlanetFadeText::FadeTextCullCallback : public osg::Drawable::CullCallback
+{
+public:
+ virtual bool cull(osg::NodeVisitor* nv,
+ osg::Drawable* drawable,
+ osg::RenderInfo* renderInfo) const
+ {
+ ossimPlanetFadeText* fadeText = dynamic_cast<ossimPlanetFadeText*>(drawable);
+ if(!fadeText) return false;
+ fadeText->setVisibleFlag(true);
+ if(fadeText->theClusterCull.get())
+ {
+ if(fadeText->theClusterCull->cull(nv, drawable, renderInfo->getState()))
+ {
+ fadeText->setVisibleFlag(false);
+ }
+ }
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
+ if(cv&&fadeText->visibleFlag())
+ {
+ const osg::Polytope& p = cv->getCurrentCullingSet().getFrustum();
+ if(!p.contains(fadeText->getPosition()))
+ {
+ fadeText->setVisibleFlag(false);
+ }
+ }
+
+ return !fadeText->theVisibleFlag;
+ }
+};
+
+struct ossimPlanetFadeText::FadeTextUpdateCallback : public osg::Drawable::UpdateCallback
+{
+// ossimPlanetFadeTextData _ftd;
+
+ virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
+ {
+
+ ossimPlanetFadeText* fadeText = dynamic_cast<ossimPlanetFadeText*>(drawable);
+ if (!fadeText) return;
+
+
+ unsigned int frameNumber = nv->getFrameStamp()->getFrameNumber();
+ if(fadeText->theFrameNumber!=frameNumber)
+ {
+ fadeText->theFrameNumber = frameNumber;
+
+ if(!fadeText->theVisibleFlag)
+ {
+ if( fadeText->theCurrentOpacity != 0.0)
+ {
+ fadeText->theCurrentOpacity -= fadeText->theFadeSpeed;
+ if(fadeText->theCurrentOpacity < 0.0)
+ {
+ fadeText->theCurrentOpacity = 0.0;
+ }
+ }
+ }
+ else if(fadeText->theCurrentOpacity != 1.0)
+ {
+ fadeText->theCurrentOpacity += fadeText->theFadeSpeed;
+ if(fadeText->theCurrentOpacity > 1.0) fadeText->theCurrentOpacity = 1.0;
+ }
+ }
+// ossimPlanetGlobalFadeText* gft = getGlobalFadeText();
+// gft->updateIfRequired(frameNumber);
+
+// ossimPlanetFadeText::ViewBlendColourMap& vbcm = fadeText->getViewBlendColourMap();
+
+// _ftd._fadeText = fadeText;
+
+// float fadeSpeed = fadeText->getFadeSpeed();
+
+// ossimPlanetGlobalFadeText::ViewFadeTextMap& vftm = gft->_viewFadeTextMap;
+// for(ossimPlanetGlobalFadeText::ViewFadeTextMap::iterator itr = vftm.begin();
+// itr != vftm.end();
+// ++itr)
+// {
+// osg::View* view = itr->first;
+// ossimPlanetGlobalFadeText::FadeTextSet& fadeTextSet = itr->second;
+// bool visible = fadeTextSet.count(fadeText)!=0;
+
+// osg::Vec4& tec = vbcm[view];
+// tec[0] = 1.0f;
+// tec[1] = 1.0f;
+// tec[2] = 1.0f;
+// if (visible)
+// {
+// if (tec[3]<1.0f)
+// {
+// tec[3] += fadeSpeed;
+// if (tec[3]>1.0f) tec[3] = 1.0f;
+// }
+
+// }
+// else
+// {
+// if (tec[3]>0.0f)
+// {
+// tec[3] -= fadeSpeed;
+// if (tec[3]<0.0f) tec[3] = 0.0f;
+// }
+// }
+// }
+ }
+};
+
+
+ossimPlanetFadeText::ossimPlanetFadeText()
+{
+ init();
+}
+
+ossimPlanetFadeText::ossimPlanetFadeText(const Text& text,const osg::CopyOp& copyop):
+ Text(text,copyop)
+{
+ init();
+}
+
+void ossimPlanetFadeText::init()
+{
+ theFadeSpeed = 0.01f;
+ setUpdateCallback(new FadeTextUpdateCallback());
+ setCullCallback(new FadeTextCullCallback());
+ theCurrentOpacity = 0.0f;
+ theVisibleFlag = false;
+ theFrameNumber = 0;
+}
+
+void ossimPlanetFadeText::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+ if(ossim::almostEqual(theCurrentOpacity, 0.0f)) return;
+
+ ossimPlanetFadeText* constCast = const_cast<ossimPlanetFadeText*>(this);
+ ossim_float64 preserveColorBackground = constCast->_backdropColor[3];
+ constCast->_backdropColor[3] = theCurrentOpacity*preserveColorBackground;
+ constCast->_color[3] = theCurrentOpacity*preserveColorBackground;
+ Text::drawImplementation(renderInfo);
+ constCast->_backdropColor[3] = preserveColorBackground;
+#if 0
+
+ // now pass on new details
+
+ ossimPlanetFadeTextUserData* userData = dynamic_cast<ossimPlanetFadeTextUserData*>(renderInfo.getUserData());
+ if (!userData)
+ {
+ if (renderInfo.getUserData())
+ {
+ osg::notify(osg::NOTICE)<<"Warning user data not of supported type."<<std::endl;
+ return;
+ }
+
+ userData = getGlobalFadeText()->createNewFadeTextUserData(renderInfo.getView());
+
+ if (!userData)
+ {
+ osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<<std::endl;
+ return;
+ }
+
+ renderInfo.setUserData(userData);
+ }
+
+ unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
+ if (frameNumber != userData->_frameNumber)
+ {
+ // new frame so must reset UserData structure.
+ userData->_frameNumber = frameNumber;
+ userData->_fadeTextInView.clear();
+ }
+
+
+
+ osgText::Text::AutoTransformCache& atc = _autoTransformCache[renderInfo.getContextID()];
+
+ osg::Matrix lmv = atc._matrix;
+ lmv.postMult(state.getModelViewMatrix());
+
+ if (renderInfo.getView() && renderInfo.getView()->getCamera())
+ {
+ // move from camera into the view space.
+ lmv.postMult(state.getInitialInverseViewMatrix());
+ lmv.postMult(renderInfo.getView()->getCamera()->getViewMatrix());
+ }
+
+ ossimPlanetFadeTextData ftd(const_cast<ossimPlanetFadeText*>(this));
+
+ ftd._vertices[0].set(osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv);
+ ftd._vertices[1].set(osg::Vec3d(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*lmv);
+ ftd._vertices[2].set(osg::Vec3d(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*lmv);
+ ftd._vertices[3].set(osg::Vec3d(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*lmv);
+
+ userData->_fadeTextInView.push_back(ftd);
+#endif
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.cpp
new file mode 100644
index 0000000..29b8cab
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.cpp
@@ -0,0 +1,616 @@
+#include <ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimGrect.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimSrtmSupportData.h>
+#include <ossim/projection/ossimImageViewProjectionTransform.h>
+
+ossimPlanetGeneralRasterElevationDatabase::ossimPlanetGeneralRasterElevationDatabase()
+ :ossimPlanetElevationDatabase()
+{
+ theOpenFlag = false;
+ theLocation = "";
+ theMaxOpenFiles = 25;
+ theMinOpenFiles = 20;
+ theCurrentInfoIdx = -1;
+// theRenderer = new ossimImageRenderer;
+// theRenderer->getResampler()->setFilterType("bilinear");
+// theProjection = new ossimEquDistCylProjection;
+// theNullHeightValue = -32768.0;
+}
+
+ossimPlanetGeneralRasterElevationDatabase::ossimPlanetGeneralRasterElevationDatabase(const ossimPlanetGeneralRasterElevationDatabase& src)
+ :ossimPlanetElevationDatabase(src),
+ theLocation(src.theLocation),
+ theOpenFlag(src.theOpenFlag),
+ theMaxOpenFiles(src.theMaxOpenFiles),
+ theMinOpenFiles(src.theMinOpenFiles)
+{
+ theCurrentInfoIdx = -1;
+// theMosaic = new ossimOrthoImageMosaic;
+// theRenderer = new ossimImageRenderer;
+// theRenderer->getResampler()->setFilterType("bilinear");
+// theProjection = new ossimEquDistCylProjection;
+ open(theLocation);
+}
+
+ossimPlanetGeneralRasterElevationDatabase::~ossimPlanetGeneralRasterElevationDatabase()
+{
+
+}
+
+ossimPlanetTextureLayer* ossimPlanetGeneralRasterElevationDatabase::dup()const
+{
+ return new ossimPlanetGeneralRasterElevationDatabase(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetGeneralRasterElevationDatabase::dupType()const
+{
+ return new ossimPlanetGeneralRasterElevationDatabase;
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetGeneralRasterElevationDatabase::updateExtents()
+{
+
+ theDirtyExtentsFlag = false;
+ return theStateCode;
+}
+
+void ossimPlanetGeneralRasterElevationDatabase::updateStats()const
+{
+ theStats->setTotalTextureSize(0);
+ theDirtyStatsFlag = false;
+
+}
+
+void ossimPlanetGeneralRasterElevationDatabase::resetStats()const
+{
+ theStats->setBytesTransferred(0);
+ theStats->setTotalTextureSize(0);
+}
+
+
+ossimPlanetTextureLayerStateCode ossimPlanetGeneralRasterElevationDatabase::open(const std::string& location)
+{
+ ossimFilename file(location);
+ bool result = false;
+ theLocation = "";
+ theExtents = new ossimPlanetExtents;
+ theCurrentInfoIdx = -1;
+
+ if(file.exists())
+ {
+ if(file.isDir())
+ {
+ ossimDirectory dir;
+
+ if(dir.open(file))
+ {
+ ossimFilename testFile;
+ if(dir.getFirst(testFile))
+ {
+ do
+ {
+ if(testFile.ext().downcase() == "ras")
+ {
+ ossimRefPtr<ossimGeneralRasterElevHandler> rasterHandler = new ossimGeneralRasterElevHandler();
+ if(rasterHandler->open(testFile))
+ {
+ osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> rasterInfo = new ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo;
+ ossimGrect grect = rasterHandler->getBoundingGndRect();
+ rasterInfo->theMinLat = ossim::min(grect.lr().latd(), grect.ul().latd());
+ rasterInfo->theMaxLat = ossim::max(grect.lr().latd(), grect.ul().latd());
+ rasterInfo->theMinLon = ossim::min(grect.lr().lond(), grect.ul().lond());
+ rasterInfo->theMaxLon = ossim::max(grect.lr().lond(), grect.ul().lond());
+ if(!result)
+ {
+ double gsd = rasterHandler->getMeanSpacingMeters();
+ theExtents->setMinMaxScale(gsd, gsd*std::pow(2.0, 12));
+ theExtents->setMinMaxLatLon(rasterInfo->theMinLat,
+ rasterInfo->theMinLon,
+ rasterInfo->theMaxLat,
+ rasterInfo->theMaxLon);
+
+ }
+ else
+ {
+ theExtents->combineMinMaxLatLon(rasterInfo->theMinLat,
+ rasterInfo->theMinLon,
+ rasterInfo->theMaxLat,
+ rasterInfo->theMaxLon);
+ }
+ result = true;
+
+ rasterInfo->theFilename = testFile.string();
+ rasterInfo->theGeneralRasterHandler = rasterHandler;
+
+ theFilePointers.push_back(rasterInfo.get());
+ }
+ }
+ }while(dir.getNext(testFile)&&!result);
+ }
+ }
+ }
+ }
+
+ theOpenFlag = result;
+ if(theOpenFlag)
+ {
+ theStateCode = ossimPlanetTextureLayer_VALID;
+ theLocation = location;
+ theCurrentInfoIdx = 0;
+ }
+ else
+ {
+ theStateCode = ossimPlanetTextureLayer_NO_SOURCE_DATA;
+ }
+
+ return theStateCode;
+}
+
+bool ossimPlanetGeneralRasterElevationDatabase::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ if(!theOpenFlag)
+ {
+ return false;
+ }
+
+ if(!theEnableFlag)
+ {
+ return false;
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return false;
+ }
+ }
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ double deltaLon = (deltaXY[0])/(double)(width);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if((gsd.x >= theExtents->getMinScale()) &&
+ (gsd.y <= theExtents->getMaxScale()))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetGeneralRasterElevationDatabase::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ ossimElevManager* manager = ossimElevManager::instance();
+ double minValue = 999999999.0;
+ double maxValue = -999999999.0;
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ double h = manager->getHeightAboveEllipsoid(ossimGpt((*optimizedOutPtr).y(), (*optimizedOutPtr).x()));
+ if(!ossim::isnan(h))
+ {
+ *bufPtr = h;
+ }
+
+ ++bufPtr;
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+#if 0
+ if(!theOpenFlag)
+ {
+ return 0;
+ }
+
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ double deltaLon = (deltaXY[0])/(double)(width);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_float64 minModelX, minModelY, maxModelX, maxModelY;
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ minModelX = points[0].x();
+ maxModelX = minModelX;
+ minModelY = minModelX;
+ maxModelY = minModelX;
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ ++optimizedOutPtr;
+ for(idxPts = 1; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if(optimizedOutPtr->x() < minModelX) minModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->x() > maxModelX) maxModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->y() < minModelY) minModelY = optimizedOutPtr->y();
+ if(optimizedOutPtr->y() > maxModelY) maxModelY = optimizedOutPtr->y();
+ }
+
+ // std::vector<ossimDpt> latLonOrigins;
+ osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> handlerInfo = 0;
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/DBL_EPSILON -1;
+ double maxValue = -1.0/DBL_EPSILON +1;
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ optimizedOutPtr = &points.front();
+ optimizedOutPtr = &points.front();
+
+ if(theFilePointers.size() == 1)
+ {
+ handlerInfo = getHandlerInfo(optimizedOutPtr->y(), optimizedOutPtr->x());
+ if(!handlerInfo) return 0;
+ ossim_float64 nullHeight = handlerInfo->theGeneralRasterHandler->getNullHeightValue();
+
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&handlerInfo.valid())
+ {
+ double h = handlerInfo->theGeneralRasterHandler->getHeightAboveMSL(ossimGpt(optimizedOutPtr->y(),
+ optimizedOutPtr->x()));
+ if(!ossim::isnan(h)&&
+ (h!=nullHeight))
+ {
+ if(theGeoRefModel.valid())
+ {
+ h+=theGeoRefModel->getGeoidOffset(optimizedOutPtr->y(), optimizedOutPtr->x());
+ }
+ *bufPtr = h;
+ if(h < minValue)
+ {
+ minValue = h;
+ }
+ if(h > maxValue)
+ {
+ maxValue = h;
+ }
+ }
+ else
+ {
+ *bufPtr = 0;
+ }
+ }
+ ++bufPtr;
+ }
+ }
+ else
+ {
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ handlerInfo = getHandlerInfo(optimizedOutPtr->y(), optimizedOutPtr->x());
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&handlerInfo.valid())
+ {
+ ossim_float64 nullHeight = handlerInfo->theGeneralRasterHandler->getNullHeightValue();
+
+ double h = handlerInfo->theGeneralRasterHandler->getHeightAboveMSL(ossimGpt(optimizedOutPtr->y(),
+ optimizedOutPtr->x()));
+ if(!ossim::isnan(h)&&
+ (h!=nullHeight))
+ {
+ if(theGeoRefModel.valid())
+ {
+ h+=theGeoRefModel->getGeoidOffset(optimizedOutPtr->y(), optimizedOutPtr->x());
+ }
+ *bufPtr = h;
+ if(h < minValue)
+ {
+ minValue = h;
+ }
+ if(h > maxValue)
+ {
+ maxValue = h;
+ }
+ }
+ else
+ {
+ *bufPtr = 0;
+ }
+ }
+ ++bufPtr;
+ }
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+#endif
+ return texture;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetGeneralRasterElevationDatabase::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ if(!theOpenFlag)
+ {
+ return 0;
+ }
+
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+ ossim_uint32 width = utility.getTileWidth();
+ ossim_uint32 height = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row,
+ col);
+
+ if(!theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ return 0;
+ }
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/height;
+ // double deltaLon = deltaX/width;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+
+ if(!theExtents->intersectsScale(gsd.y-FLT_EPSILON,
+ gsd.y+FLT_EPSILON))//gsd.y <= theExtents.theMaxGsd)
+ {
+ return 0;
+ }
+
+ // double minSubRectLat = ossim::max(theExtents->getMinLat(),
+ // minLat);
+ //double minSubRectLon = ossim::max(theExtents->getMinLon(),
+ // minLon);
+ // double maxSubRectLat = ossim::min(theExtents->getMaxLat(),
+ // maxLat);
+ //double maxSubRectLon = ossim::min(theExtents->getMaxLon(),
+ // maxLon);
+ //ossim_int32 wholeMinLat = (ossim_int32)std::floor(minSubRectLat);
+ //ossim_int32 wholeMinLon = (ossim_int32)std::floor(minSubRectLon);
+ //ossim_int32 wholeMaxLat = (ossim_int32)std::floor(maxSubRectLat);
+ //ossim_int32 wholeMaxLon = (ossim_int32)std::floor(maxSubRectLon);
+
+
+ //ossim_int32 lat = wholeMaxLat;
+ //ossim_int32 lon = wholeMinLon;
+ osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> handlerInfo = 0;//theFilePointers[theCurrentInfoIdx];
+ texture = new ossimPlanetImage(ossimPlanetTerrainTileId(0,
+ level,
+ col,
+ row));
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width,
+ height);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ utility.createGridPoints(points,
+ level,
+ row,
+ col,
+ height,
+ width);
+
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/DBL_EPSILON -1;
+ double maxValue = -1.0/DBL_EPSILON +1;
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ for(idxPts = 0; idxPts < nPoints; ++idxPts)
+ {
+ utility.getLatLon(latLonPoint, points[idxPts]);
+ handlerInfo = getHandlerInfo(latLonPoint[0], latLonPoint[1]);
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&handlerInfo.valid())
+ {
+ ossim_float64 nullHeight = handlerInfo->theGeneralRasterHandler->getNullHeightValue();
+ utility.getLatLon(latLonPoint, points[idxPts]);
+ double h = handlerInfo->theGeneralRasterHandler->getHeightAboveMSL(ossimGpt(latLonPoint[0],
+ latLonPoint[1]));
+ if(!ossim::isnan(h)&&(h!=nullHeight))
+ {
+ if(theGeoRefModel.valid())
+ {
+ h+=theGeoRefModel->getGeoidOffset(latLonPoint[0], latLonPoint[1]);
+ }
+ *bufPtr = h;
+ if(*bufPtr < minValue)
+ {
+ minValue = *bufPtr;
+ }
+ if(*bufPtr > maxValue)
+ {
+ maxValue = *bufPtr;
+ }
+ }
+ }
+ ++bufPtr;
+ }
+
+ compositeData->validate();
+
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+
+ return texture;
+}
+osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> ossimPlanetGeneralRasterElevationDatabase::getHandlerInfo(const double& lat,
+ const double& lon)
+{
+ if(theFilePointers.size() < 1) return 0;
+
+ osg::ref_ptr<ossimPlanetGeneralRasterElevationDatabase::GeneralRasterInfo> result = 0;
+
+ if(theCurrentInfoIdx < 0) theCurrentInfoIdx = 0;
+ result = theFilePointers[theCurrentInfoIdx];
+ if((lat >= result->theMinLat)&&
+ (lat <= result->theMaxLat)&&
+ (lon >= result->theMinLon)&&
+ (lon <= result->theMaxLon))
+ {
+ return result;
+ }
+ theCurrentInfoIdx = 0;
+ while(theCurrentInfoIdx < (int)theFilePointers.size())
+ {
+ result = theFilePointers[theCurrentInfoIdx];
+ if((lat >= result->theMinLat)&&
+ (lat <= result->theMaxLat)&&
+ (lon >= result->theMinLon)&&
+ (lon <= result->theMaxLon))
+ {
+ return result;
+ }
+ ++theCurrentInfoIdx;
+
+ }
+ theCurrentInfoIdx = 0;
+
+ return 0;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetGeocoder.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetGeocoder.cpp
new file mode 100644
index 0000000..f11c703
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetGeocoder.cpp
@@ -0,0 +1,81 @@
+#include <ossimPlanet/ossimPlanetGeocoder.h>
+#include <sstream>
+#include <iostream>
+static std::istream& geocoderskipws(std::istream& in)
+{
+ int c = in.peek();
+ while((c == ' ') ||
+ (c == '\t') ||
+ (c == '\n')||
+ (c == '\r'))
+ {
+ in.ignore(1);
+ c = in.peek();
+ }
+
+ return in;
+}
+ossimPlanetGoecoder::ossimPlanetGeocoderLocation::ossimPlanetGeocoderLocation()
+{
+ theMetaInformation = new ossimXmlNode;
+ theMetaInformation->setTag("kml");
+ theNameNode = new ossimXmlNode;
+ theNameNode->setTag("name");
+ theMetaInformation->addChildNode(theNameNode.get());
+ thePlacemarkNode = new ossimXmlNode;
+ thePlacemarkNode->setTag("Placemark");
+ theMetaInformation->addChildNode(thePlacemarkNode.get());
+ theAddressNode = new ossimXmlNode;
+ theAddressNode->setTag("Address");
+ thePointNode = new ossimXmlNode;
+ theCoordinatesNode = new ossimXmlNode;
+ theCoordinatesNode->setText("0.0, 0.0, 0.0");
+ thePointNode->addChildNode(theCoordinatesNode.get());
+
+ theMetaInformation->addChildNode(theNameNode.get());
+ theMetaInformation->addChildNode(thePlacemarkNode.get());
+ theMetaInformation->addChildNode(theAddressNode.get());
+ theMetaInformation->addChildNode(thePointNode.get());
+}
+
+void ossimPlanetGoecoder::ossimPlanetGeocoderLocation::setLocation(const ossimGpt& location)
+{
+ theCoordinatesNode->setText(ossimString::toString(location.latd())+ "," +
+ ossimString::toString(location.lond())+ ", 0.0");
+
+}
+
+ossimGpt ossimPlanetGoecoder::ossimPlanetGeocoderLocation::getLocation()const
+{
+ ossimGpt result;
+ std::istringstream in(theCoordinatesNode->getText());
+
+ char c;
+ double lat, lon;
+
+ in >> lat >> geocoderskipws >> c >> geocoderskipws >>lon;
+ result.latd(lat);
+ result.lond(lon);
+
+ return result;
+}
+
+void ossimPlanetGoecoder::ossimPlanetGeocoderLocation::setName(const ossimString& name)
+{
+ theNameNode->setText(name);
+}
+
+ossimString ossimPlanetGoecoder::ossimPlanetGeocoderLocation::getName()const
+{
+ return theNameNode->getText();
+}
+
+ossimString ossimPlanetGoecoder::ossimPlanetGeocoderLocation::getAddress()const
+{
+ return theAddressNode->getText();
+}
+
+void ossimPlanetGoecoder::ossimPlanetGeocoderLocation::setAddress(const ossimString& address)
+{
+ theAddressNode->setText(address);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetGrid.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetGrid.cpp
new file mode 100644
index 0000000..cf458d8
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetGrid.cpp
@@ -0,0 +1,1100 @@
+#include <ossimPlanet/ossimPlanetGrid.h>
+#include <ossimPlanet/ossimPlanetPlaneGrid.h>
+#include <ossimPlanet/ossimPlanetCubeGrid.h>
+#include <osg/Vec2d>
+#include <osg/io_utils>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <iomanip>
+
+void ossimPlanetGrid::numberOfTilesPerFace(ossim_uint32 lod, ossim_uint64& tilesWide, ossim_uint64& tilesHigh) const
+{
+ ossim_uint64 value = 1<<lod;
+
+ tilesWide = value;
+ tilesHigh = value;
+}
+
+void ossimPlanetGrid::bounds(const ossimPlanetTerrainTileId& tileId, GridBound& bound)const
+{
+ ossim_float64 w,h;
+ GridPoint gridPoint;
+ origin(tileId, gridPoint);
+ widthHeight(tileId, w, h);
+
+ bound.theMinx = gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ bound.theMiny = gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ bound.theWidth = w;
+ bound.theHeight = h;
+ bound.theFace = tileId.face();
+}
+
+void ossimPlanetGrid::boundsToModel(const ossimPlanetTerrainTileId& tileId,
+ ModelPoint& p0,
+ ModelPoint& p1,
+ ModelPoint& p2,
+ ModelPoint& p3)const
+{
+ GridBound bound;
+ bounds(tileId, bound);
+ globalGridToModel(GridPoint(tileId.face(),bound.minx(), bound.miny()),
+ p0);
+ globalGridToModel(GridPoint(tileId.face(),bound.maxx(), bound.miny()),
+ p1);
+ globalGridToModel(GridPoint(tileId.face(),bound.maxx(), bound.maxy()),
+ p2);
+ globalGridToModel(GridPoint(tileId.face(),bound.minx(), bound.maxy()),
+ p3);
+}
+
+void ossimPlanetGrid::centerGrid(const ossimPlanetTerrainTileId& tileId, GridPoint& gridPoint)
+{
+ ossim_float64 w,h;
+ origin(tileId, gridPoint);
+ widthHeight(tileId, w, h);
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] += (w*.5);
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] += (h*.5);
+}
+
+void ossimPlanetGrid::centerModel(const ossimPlanetTerrainTileId& tileId, ModelPoint& modelPoint)
+{
+ GridPoint gridPoint;
+ centerGrid(tileId, gridPoint);
+ globalGridToModel(gridPoint, modelPoint);
+}
+
+void ossimPlanetGrid::widthHeight(const ossimPlanetTerrainTileId& tileId, ossim_float64& width, ossim_float64& height)const
+{
+ // assume square in NDC 0..1 and divide by the 2^level
+ //
+ ossim_float64 value = 1.0/(ossim_float64)(1<<tileId.level());
+
+ width = value;
+ height = value;
+}
+
+void ossimPlanetGrid::origin(const ossimPlanetTerrainTileId& tileId, GridPoint& gridPoint)const
+{
+ ossim_float64 w,h;
+
+ // get the width hieght in global 0..1 grid space.
+ widthHeight(tileId, w, h);
+ gridPoint.theFace = tileId.face();
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = tileId.x()*w;
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = tileId.y()*h;
+}
+
+void ossimPlanetGrid::getUnitsPerPixel(osg::Vec2d& unitsPerPixel,
+ const ossimPlanetTerrainTileId& tileId,
+ ossim_uint32 w,
+ ossim_uint32 h,
+ const ossimUnitType unitType)const
+{
+ unitsPerPixel[0] = unitsPerPixel[1] = 0.0;
+ if(theModelType == GEODETIC_MODEL)
+ {
+ osg::Vec2d modelWH;
+
+ widthHeightInModelSpace(tileId, modelWH);
+ ossimUnitConversionTool toolX(modelWH[0], OSSIM_DEGREES);
+ ossimUnitConversionTool toolY(modelWH[1], OSSIM_DEGREES);
+ unitsPerPixel[0] = toolX.getValue(unitType);
+ unitsPerPixel[1] = toolY.getValue(unitType);
+ unitsPerPixel[0] /= w;
+ unitsPerPixel[1] /= h;
+ }
+}
+
+bool ossimPlanetGrid::convertToGeographicExtents(const ossimPlanetTerrainTileId& tileId,
+ ossimPlanetExtents& extents,
+ ossim_uint32 w, ossim_uint32 h)const
+{
+ static const ossimGpt wgs84Point;
+ bool result = false;
+ if(theModelType == GEODETIC_MODEL)
+ {
+ ModelPoint minPoint, maxPoint;
+ osg::Vec2d modelWH;
+ modelBound(tileId, minPoint, maxPoint);
+ extents.setMinMaxLatLon(minPoint.y(), minPoint.x(),
+ maxPoint.y(), maxPoint.x());
+ widthHeightInModelSpace(tileId, modelWH);
+ ossim_float64 average = (modelWH[0]+modelWH[1])*.5;
+ ossim_float64 mpd = wgs84Point.metersPerDegree().y;
+ ossim_float64 mpp = (mpd*average)/((w+h)*.5);
+ // we will set the gsd as the center for this tile and then make a range that covers to approximately
+ // the next level down and the next level up.
+ //
+ extents.setMinMaxScale(mpp*.5, mpp*2.0);
+
+ result = true;
+ }
+ return result;
+}
+
+void ossimPlanetGrid::localNdcToGlobalGrid(const ossimPlanetTerrainTileId& tileId, const LocalNdcPoint& localNdc, GridPoint& globalGrid)const
+{
+ GridBound b;
+ bounds(tileId, b);
+
+ globalGrid.setZ(localNdc.z());
+ globalGrid.setX(b.minx() + b.width()*localNdc.x());
+ globalGrid.setY(b.miny() + b.height()*localNdc.y());
+ globalGrid.setFace(tileId.face());
+}
+
+void ossimPlanetGrid::localNdcToModel(const ossimPlanetTerrainTileId& tileId, const LocalNdcPoint& localNdc, ModelPoint& model)const
+{
+ GridPoint gridPoint;
+ localNdcToGlobalGrid(tileId, localNdc, gridPoint);
+ globalGridToModel(gridPoint, model);
+}
+
+void ossimPlanetCubeGrid2::getRootIds(TileIds &ids) const
+{
+ ids.push_back(ossimPlanetTerrainTileId(0,0,0,0));
+ ids.push_back(ossimPlanetTerrainTileId(1,0,0,0));
+ ids.push_back(ossimPlanetTerrainTileId(2,0,0,0));
+ ids.push_back(ossimPlanetTerrainTileId(3,0,0,0));
+ ids.push_back(ossimPlanetTerrainTileId(4,0,0,0));
+ ids.push_back(ossimPlanetTerrainTileId(5,0,0,0));
+}
+
+
+void ossimPlanetGrid::getInternationalDateLineCrossings(const ossimPlanetTerrainTileId& tileId,
+ std::vector<osg::Vec2d>& minMaxPairs)const
+{
+ ModelPoint ll, lr, ur, ul;
+
+ GridBound bound;
+ bounds(tileId, bound);
+
+ globalGridToModel(GridPoint(tileId.face(), bound.minx(), bound.miny()), ll);
+ globalGridToModel(GridPoint(tileId.face(), bound.maxx(), bound.miny()), lr);
+ globalGridToModel(GridPoint(tileId.face(), bound.maxx(), bound.maxy()), ur);
+ globalGridToModel(GridPoint(tileId.face(), bound.minx(), bound.maxy()), ul);
+ if(!crossesInternationalDateLine(tileId)||(theModelType!=GEODETIC_MODEL))
+ {
+ double minLon = ossim::min(ll.x(), ossim::min(lr.x(), ossim::min(ur.x(), ul.x())));
+ double maxLon = ossim::max(ll.x(), ossim::max(lr.x(), ossim::max(ur.x(), ul.x())));
+ minMaxPairs.push_back(osg::Vec2d(minLon, maxLon));
+ }
+ else if(theModelType == GEODETIC_MODEL)
+ {
+
+ osg::Vec2d pt;
+ pt[0] = -180.0;
+ pt[1] = -180.0;
+ if(ul.x() < FLT_EPSILON)
+ {
+ if(ul.x() > pt[1])
+ {
+ pt[1] = ul.x();
+ }
+ }
+ if(ur.x() < FLT_EPSILON)
+ {
+ if(ur.x() > pt[1])
+ {
+ pt[1] = ur.x();
+ }
+ }
+ if(lr.x() < FLT_EPSILON)
+ {
+ if(lr.x() > pt[1])
+ {
+ pt[1] = lr.x();
+ }
+ }
+ if(ll.x() < FLT_EPSILON)
+ {
+ if(ll.x() > pt[1])
+ {
+ pt[1] = ll.x();
+ }
+ }
+ minMaxPairs.push_back(pt);
+
+ pt[0] = 180.0;
+ pt[1] = 180.0;
+ if(ul.x() > -FLT_EPSILON)
+ {
+ if(ul.x() < pt[0])
+ {
+ pt[0] = ul.x();
+ }
+ }
+ if(ur.x() > -FLT_EPSILON)
+ {
+ if(ur.x() < pt[0])
+ {
+ pt[0] = ur.x();
+ }
+ }
+ if(lr.x() > -FLT_EPSILON)
+ {
+ if(lr.x() < pt[0])
+ {
+ pt[0] = lr.x();
+ }
+ }
+ if(ll.x() > -FLT_EPSILON)
+ {
+ if(ll.x() < pt[0])
+ {
+ pt[0] = ll.x();
+ }
+ }
+ minMaxPairs.push_back(pt);
+ }
+}
+
+void ossimPlanetGrid::createModelPoints(const ossimPlanetTerrainTileId& tileId,
+ ossim_uint32 w,
+ ossim_uint32 h,
+ ossimPlanetGrid::ModelPoints& modelPoints,
+ ossim_uint32 padding)const
+{
+ ossim_int32 signedPadding = padding;
+ ossim_int32 rowIdx = 0;
+ ossim_int32 colIdx = 0;
+ ossim_float64 incH = 1.0/(h-1);
+ ossim_float64 incW = 1.0/(w-1);
+ ossim_int32 maxH = h + padding;
+ ossim_int32 maxW = w + padding;
+ ossimPlanetGrid::LocalNdcPoint localPoint;
+ ossimPlanetGrid::ModelPoint modelPoint;
+ modelPoints.clear();
+ for(rowIdx = -signedPadding; rowIdx < maxH;++rowIdx)
+ {
+ localPoint.setY(rowIdx*incH);
+ for(colIdx = -signedPadding; colIdx < maxW;++colIdx)
+ {
+ localPoint.setX(colIdx*incW);
+ localNdcToModel(tileId, localPoint, modelPoint);
+ modelPoints.push_back(modelPoint);
+ }
+ }
+}
+
+bool ossimPlanetGrid::crossesInternationalDateLine(const ossimPlanetTerrainTileId& tileId)const
+{
+ if(theModelType != GEODETIC_MODEL) return false;
+ ModelPoint minPoint, maxPoint;
+ modelBound(tileId, minPoint, maxPoint);
+ return (fabs(minPoint.x()-maxPoint.x()) > 180.0);
+}
+
+void ossimPlanetGrid::modelBound(const ossimPlanetTerrainTileId& tileId,
+ ModelPoint& minPoint, ModelPoint& maxPoint)const
+{
+ ModelPoints points;
+ createModelPoints(tileId,
+ 3,
+ 3,
+ points);
+ minPoint.setX(1.0/FLT_EPSILON);
+ minPoint.setY(1.0/FLT_EPSILON);
+ minPoint.setZ(1.0/FLT_EPSILON);
+ maxPoint.setX(-1.0/FLT_EPSILON);
+ maxPoint.setY(-1.0/FLT_EPSILON);
+ maxPoint.setZ(-1.0/FLT_EPSILON);
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = points.size();
+ osg::Vec3d latLon;
+ for(idx = 0; idx < size; ++idx)
+ {
+ minPoint.setX(ossim::min(minPoint.x(), points[idx].x()));
+ minPoint.setY(ossim::min(minPoint.y(), points[idx].y()));
+ minPoint.setZ(ossim::min(minPoint.z(), points[idx].z()));
+ maxPoint.setX(ossim::max(maxPoint.x(), points[idx].x()));
+ maxPoint.setY(ossim::max(maxPoint.y(), points[idx].y()));
+ maxPoint.setZ(ossim::max(maxPoint.z(), points[idx].z()));
+ }
+}
+
+void ossimPlanetCubeGrid2::modelToGlobalGrid(const ModelPoint& modelPoint,
+ GridPoint& gridPoint)const
+{
+ osg::Vec2d ll((ossim::clamp((double)modelPoint.y(),
+ (double)-90.0, (double)90.0)+90)/180,
+ (ossim::wrap((double)modelPoint.x(),
+ (double)-180.0, (double)180.0)+180)/360);
+ int face_x = (int)(4 * ll[ossimPlanetGrid::LON_IDX]);
+ int face_y = (int)(2 * ll[ossimPlanetGrid::LAT_IDX] + 0.5);
+ if(face_x == 4)
+ {
+ face_x = 3;
+ }
+ if(face_y == 1)
+ {
+ gridPoint.theFace = face_x;
+ }
+ else
+ {
+ gridPoint.theFace = face_y < 1 ? 5 : 4;
+ }
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 4 * ll[ossimPlanetGrid::LON_IDX] - face_x;
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 2 * ll[ossimPlanetGrid::LAT_IDX] - 0.5;
+ if(gridPoint.theFace < 4) // equatorial calculations done
+ {
+ // gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = 1-gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY];
+ return;
+ }
+
+ double tmp=0.0;
+ if(gridPoint.theFace == 4) // north polar face
+ {
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 1.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = (2 * (gridPoint.theXYZ[ossimPlanetGrid::X_IDX] - 0.5) *
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] + 0.5);
+ switch(face_x)
+ {
+ case 0: // bottom
+ {
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ break;
+ }
+ case 1: // right side, swap and reverse lat
+ {
+ tmp = gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 0.5 + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = tmp;
+ break;
+ }
+ case 2: // top; reverse lat and lon
+ {
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 1 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 0.5 + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ break;
+ }
+ case 3: // left side; swap and reverse lon
+ {
+ tmp = gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX]= 1 - tmp;
+ break;
+ }
+ }
+ }
+ else // south polar face
+ {
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] += 0.5;
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = (2 * (gridPoint.theXYZ[ossimPlanetGrid::X_IDX] - 0.5) * gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] + 0.5);
+ switch(face_x)
+ {
+ case 0: // left
+ {
+ tmp = gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = tmp;
+ break;
+ }
+ case 1: // top
+ {
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 0.5 + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ break;
+ }
+ case 2: // right
+ {
+ tmp = gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 0.5 + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 1 - tmp;
+ break;
+ }
+ case 3: // bottom
+ {
+ gridPoint.theXYZ[ossimPlanetGrid::X_IDX] = 1 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ break;
+ }
+ }
+ }
+}
+
+void ossimPlanetCubeGrid2::globalGridToModel(const GridPoint& gridPoint,
+ ModelPoint& modelPoint)const
+{
+ globalGridToModelLat45(gridPoint, modelPoint);
+}
+
+void ossimPlanetCubeGrid2::globalGridToModelLat45(const GridPoint& gridPoint,
+ ModelPoint& modelPoint)const
+{
+
+ double offset = 0.0;
+ osg::Vec2d s(ossim::clamp(gridPoint.theXYZ[ossimPlanetGrid::X_IDX], 0.0, 1.0),
+ ossim::clamp(gridPoint.theXYZ[ossimPlanetGrid::Y_IDX], 0.0, 1.0));
+ modelPoint.theXYZ[ossimPlanetGrid::Z_IDX] = gridPoint.z();
+ if(gridPoint.theFace < 4)
+ {
+ s[ossimPlanetGrid::X_IDX] = (gridPoint.theXYZ[ossimPlanetGrid::X_IDX]+gridPoint.theFace)*.25;
+ s[ossimPlanetGrid::Y_IDX] = (gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] + 0.5)*0.5;
+ // latLon.x() = s[ossimPlanetGridUtility::GRIDX]*360.0 - 180.0;
+ // latLon[ossimPlanetGridUtility::LAT] = 90 - s[ossimPlanetGridUtility::GRIDY]*180.0;
+ // return;
+ }
+ else if(gridPoint.theFace == 4)
+ {
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] < gridPoint.theXYZ[ossimPlanetGrid::Y_IDX])
+ {
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] < 1.0)
+ {
+ s[ossimPlanetGrid::X_IDX] = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ s[ossimPlanetGrid::Y_IDX] = gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ offset += 3;
+ }
+ else
+ {
+ s[ossimPlanetGrid::Y_IDX] = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ s[ossimPlanetGrid::X_IDX] = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ offset += 2;
+ }
+ }
+ else if((gridPoint.theXYZ[ossimPlanetGrid::X_IDX] + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX]) >= 1.0)
+ {
+ s[ossimPlanetGrid::X_IDX] = gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ s[ossimPlanetGrid::Y_IDX] = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ offset += 1.0;
+ }
+ s[ossimPlanetGrid::X_IDX] -= s[ossimPlanetGrid::Y_IDX];
+ if(!ossim::almostEqual(s[ossimPlanetGrid::Y_IDX], .5))
+ {
+ s[ossimPlanetGrid::X_IDX] *= .5/(.5 - s[ossimPlanetGrid::Y_IDX]);
+ }
+ s[ossimPlanetGrid::X_IDX] = (s[ossimPlanetGrid::X_IDX] + offset)*0.25;
+ s[ossimPlanetGrid::Y_IDX] = (s[ossimPlanetGrid::Y_IDX] + 1.5)*.5;
+ }
+ else if(gridPoint.theFace == 5)
+ {
+ offset = 1.0;
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] > gridPoint.theXYZ[ossimPlanetGrid::Y_IDX])
+ {
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] >= 1.0)
+ {
+ s[ossimPlanetGrid::X_IDX] = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ s[ossimPlanetGrid::Y_IDX] = gridPoint.theXYZ[ossimPlanetGrid::X_IDX] - .5;
+ offset += 1.0;
+ }
+ else
+ {
+ s[ossimPlanetGrid::X_IDX] = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ s[ossimPlanetGrid::Y_IDX] = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ offset+=2;
+ }
+ }
+ else
+ {
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] < 1.0)
+ {
+ s[ossimPlanetGrid::X_IDX] = gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ s[ossimPlanetGrid::Y_IDX] = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ offset -= 1.0;
+ }
+ else
+ {
+ s[ossimPlanetGrid::Y_IDX] = gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] - 0.5;
+ }
+ }
+ if(!ossim::almostEqual((double)s[ossimPlanetGrid::Y_IDX], (double)0.0))
+ {
+ // s[ossimPlanetGrid::X_IDX] = ((s[ossimPlanetGrid::X_IDX] - 0.5)*.5)/s[ossimPlanetGrid::Y_IDX] + .5;
+ s[ossimPlanetGrid::X_IDX] = ((s[ossimPlanetGrid::X_IDX] - 0.5)*.5)/s[ossimPlanetGrid::Y_IDX] + .5;
+ }
+ s[ossimPlanetGrid::X_IDX] = (s[ossimPlanetGrid::X_IDX] + offset) *0.25;
+ s[ossimPlanetGrid::Y_IDX] *=.5;
+ }
+ modelPoint.theXYZ[ossimPlanetGrid::X_IDX] = s[ossimPlanetGrid::X_IDX]*360.0 - 180.0;
+ modelPoint.theXYZ[ossimPlanetGrid::Y_IDX] = s[ossimPlanetGrid::Y_IDX]*180.0 - 90;
+ modelPoint.theXYZ[ossimPlanetGrid::Z_IDX] = gridPoint.z();
+}
+
+void ossimPlanetCubeGrid2::globalGridToModelLat67_5(const GridPoint& gridPoint, ModelPoint& modelPoint)const
+{
+
+ // double offset = 0.0;
+ osg::Vec2d s(ossim::clamp(gridPoint.theXYZ[ossimPlanetGrid::X_IDX], 0.0, 1.0),
+ ossim::clamp(gridPoint.theXYZ[ossimPlanetGrid::Y_IDX], 0.0, 1.0));
+ modelPoint.theXYZ[ossimPlanetGrid::Z_IDX] = gridPoint.z();
+ if(gridPoint.theFace < 24)
+ {
+ modelPoint.setX(gridPoint.x()*360.0 - 180.0);
+ modelPoint.setY(-67.5 + gridPoint.y()*135);
+ return;
+ }
+ else if(gridPoint.theFace == 24)// north cap
+ {
+ }
+ else if(gridPoint.theFace == 25)
+ {
+ }
+}
+
+void ossimPlanetCubeGrid2::widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId, osg::Vec2d& deltaXY)const
+{
+ GridBound b;
+
+ bounds(tileId, b);
+ ossim_float64 multiplier = 90;
+ deltaXY[0] = multiplier*b.width();
+ deltaXY[1] = multiplier*b.height();
+}
+
+
+bool ossimPlanetCubeGrid2::findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints)const
+{
+ ossimDrect modelClipBound;
+ ossimDrect modelBound(minPoint.x(), maxPoint.y(), maxPoint.x(), minPoint.y(), OSSIM_RIGHT_HANDED);
+ ossimDrect modelFaceBound;
+ modelFaceBound.makeNan();
+ double epsilon = 1e-10;
+ if(face < 4)
+ {
+ // ossim_uint32 dx=0;
+ ossim_float64 originLat=-45, originLon=-180;
+ originLon = -180.0+(face*90);
+ modelFaceBound = ossimDrect(originLon,
+ originLat+90-epsilon, originLon + 90.0-epsilon, originLat, OSSIM_RIGHT_HANDED);
+ }
+ else if(face == 4)
+ {
+ modelFaceBound = ossimDrect(-180.0, 90.0, 180.0, 45.0, OSSIM_RIGHT_HANDED);
+
+ }
+ else if(face == 5)
+ {
+ modelFaceBound = ossimDrect(-180.0, -45.0-epsilon, 180.0-epsilon, -90.0, OSSIM_RIGHT_HANDED);
+ }
+ bool result = modelFaceBound.intersects(modelBound);
+ if(result)
+ {
+ modelClipBound = modelBound.clipToRect(modelFaceBound);
+
+ std::vector<ossimDpt> gridPoints;
+ ossim_uint32 idxY = 0;
+ ossim_uint32 idxX = 0;
+ double deltaModelX = modelClipBound.ur().x-modelClipBound.ll().x;
+ double deltaModelY = modelClipBound.ur().y-modelClipBound.ll().y;
+ ossimDpt ll = modelClipBound.ll();
+
+ ossimPlanetGrid::GridPoint gridPoint;
+ for(idxY = 0; idxY <numberOfPoints; ++idxY)
+ {
+ for(idxX = 0; idxX < numberOfPoints; ++idxX)
+ {
+ double tx = (double)idxX/(numberOfPoints-1);
+ double ty = (double)idxY/(numberOfPoints-1);
+
+ ossimPlanetGrid::ModelPoint modelPoint(ll.x + deltaModelX*tx,
+ ll.y + deltaModelY*ty);
+ modelToGlobalGrid(modelPoint, gridPoint);
+ gridPoints.push_back(ossimDpt(gridPoint.x(), gridPoint.y()));
+ }
+ }
+ ossimDrect rect(gridPoints, OSSIM_RIGHT_HANDED);
+ bound.theMinx = rect.ll().x;
+ bound.theMiny = rect.ll().y;
+ bound.theWidth = (rect.ur().x-rect.ll().x);
+ bound.theHeight= (rect.ur().y-rect.ll().y);
+ bound.theFace = face;
+ }
+ return result;
+}
+
+ossim_uint32 ossimPlanetCubeGrid2::numberOfFaces()const
+{
+ return 6;
+}
+
+ossimPlanetGridUtility* ossimPlanetCubeGrid2::newBackwardCompatableGrid(ossim_uint32 width,
+ ossim_uint32 height)const
+{
+ return new ossimPlanetCubeGrid(width, height);
+}
+
+bool ossimPlanetCubeGrid2::isPolar(const ossimPlanetTerrainTileId& id)const
+{
+ return (id.face() >3);
+}
+
+void ossimPlanetPlaneGrid2::getRootIds(TileIds &ids) const
+{
+ ids.push_back(ossimPlanetTerrainTileId(0,0,0,0));
+ ids.push_back(ossimPlanetTerrainTileId(1,0,0,0));
+}
+
+void ossimPlanetPlaneGrid2::globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const
+{
+ modelPoint.setY(180.0*gridPoint.y() - 90.0);
+ if(gridPoint.face() == 0)
+ {
+ modelPoint.setX(180.0*gridPoint.x() - 180.0);
+ }
+ else
+ {
+ modelPoint.setX(180.0*gridPoint.x());
+ }
+
+ modelPoint.setZ(gridPoint.z());
+}
+
+void ossimPlanetPlaneGrid2::modelToGlobalGrid(const ModelPoint& modelPoint,
+ GridPoint& gridPoint)const
+{
+ gridPoint.setY((modelPoint.y()+90.0)/180.0);
+ if(modelPoint.x() < 0.0)
+ {
+ gridPoint.setFace(0);
+ gridPoint.setX(modelPoint.x()/180.0 + 1.0);
+ }
+ else
+ {
+ gridPoint.setFace(1);
+ gridPoint.setX(modelPoint.x()/180.0);
+ }
+
+ gridPoint.setZ(modelPoint.z());
+}
+
+void ossimPlanetPlaneGrid2::widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId,
+ osg::Vec2d& deltaXY)const
+{
+ GridBound b;
+
+ bounds(tileId, b);
+
+ deltaXY[0] = 180.0*b.width();
+ deltaXY[1] = 180.0*b.height();
+}
+
+bool ossimPlanetPlaneGrid2::findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 /* numberOfPoints */)const
+{
+ ossimDrect modelClipBound;
+ ossimDrect modelBound(minPoint.x(), maxPoint.y(), maxPoint.x(), minPoint.y(), OSSIM_RIGHT_HANDED);
+ ossimDrect modelFaceBound;
+ if(face == 0)
+ {
+ modelFaceBound = ossimDrect(-180.0, 90.0, 0.0, -90.0, OSSIM_RIGHT_HANDED);
+ }
+ else
+ {
+ modelFaceBound = ossimDrect(0.0, 90, 180.0, -90.0, OSSIM_RIGHT_HANDED);
+ }
+ bool result = modelFaceBound.intersects(modelBound);
+ if(result)
+ {
+ modelClipBound = modelBound.clipToRect(modelFaceBound);
+// std::cout << "modelClipBound " << modelClipBound << std::endl;
+ }
+
+ bound.theMiny = (90.0 + modelClipBound.ll().y)/180.0;
+ bound.theMinx = modelClipBound.ll().x/180.0;
+ if(face == 0)
+ {
+ bound.theMinx+= 1.0;
+ }
+
+ bound.setFace(face);
+ bound.theWidth = (modelClipBound.ur().x-modelClipBound.ll().x)/180.0;
+ bound.theHeight = (modelClipBound.ur().y-modelClipBound.ll().y)/180.0;
+
+// std::cout << "bound.theMinX = " << bound.theMinx << "\n"
+// << "bound.theMinY = " << bound.theMiny << "\n";
+ return result;
+}
+
+ossim_uint32 ossimPlanetPlaneGrid2::numberOfFaces()const
+{
+ return 12;
+}
+
+ossimPlanetGridUtility* ossimPlanetPlaneGrid2::newBackwardCompatableGrid(ossim_uint32 width,
+ ossim_uint32 height)const
+{
+ return new ossimPlanetPlaneGrid(width, height);
+}
+
+ossimPlanetAdjustableCubeGrid::ossimPlanetAdjustableCubeGrid(CapLocation location)
+:ossimPlanetCubeGrid2()
+{
+ setCapLocation(location);
+}
+
+void ossimPlanetAdjustableCubeGrid::setCapLocation(CapLocation location)
+{
+ theCapLocation = location;
+ switch(location)
+ {
+ case LOW_CAP:
+ {
+ thePolarLat = 45.0;
+ break;
+ }
+ case MEDIUM_LOW_CAP:
+ {
+ thePolarLat = 67.5;
+ break;
+ }
+ case MEDIUM_CAP:
+ {
+ thePolarLat = 78.75;
+ break;
+ }
+ case MEDIUM_HIGH_CAP:
+ {
+ thePolarLat = 84.375;
+ break;
+ }
+ case HIGH_CAP:
+ {
+ thePolarLat = 87.1875;
+ break;
+ }
+ default:
+ {
+ thePolarLat = 78.75;
+ break;
+ }
+ }
+ theUpperEquatorialBandLatDelta = thePolarLat-45.0;
+ thePolarWidth = 2*(90-thePolarLat);// used in calculating crude ground distance.
+}
+
+void ossimPlanetAdjustableCubeGrid::getRootIds(TileIds &ids) const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ ossimPlanetCubeGrid2::getRootIds(ids);
+ }
+ else
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < numberOfFaces(); ++idx)
+ {
+ ids.push_back(ossimPlanetTerrainTileId(idx,0,0,0));
+ }
+ }
+}
+
+void ossimPlanetAdjustableCubeGrid::globalGridToModel(const GridPoint& gridPoint, ModelPoint& modelPoint)const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ ossimPlanetCubeGrid2::globalGridToModel(gridPoint, modelPoint);
+ return;
+ }
+ double xt = ossim::clamp(gridPoint.x(), 0.0, 1.0);
+ double yt = ossim::clamp(gridPoint.y(), 0.0, 1.0);
+ // equatorial
+ if(gridPoint.face() < 4)
+ {
+ modelPoint.setY(90.0*yt - 45.0);
+ modelPoint.setX(-180 + 90*(gridPoint.face() + xt));
+ }
+ // northern band
+ else if(gridPoint.face() < 8)
+ {
+ modelPoint.setY(45+theUpperEquatorialBandLatDelta*yt);
+ modelPoint.setX(-180 + 90.0*(gridPoint.face()-4 + xt));
+ }
+ // southern band
+ else if(gridPoint.face() < 12)
+ {
+ modelPoint.setY(-thePolarLat + theUpperEquatorialBandLatDelta*yt);
+ modelPoint.setX(-180 + 90.0*(gridPoint.face()-8 +xt));
+ }
+ // north polar cap
+ else if(gridPoint.face() == 12)
+ {
+ GridPoint gPt(gridPoint);
+
+ gPt.setFace(4);
+ ossimPlanetCubeGrid2::globalGridToModel(gPt, modelPoint);
+ // since we are using the formula for a 45 degree lat cube we will remap
+ // to our polar hack location.
+ //
+ double latT = (modelPoint.theXYZ[ossimPlanetGrid::Y_IDX] - 45.0)/45;
+ modelPoint.theXYZ[ossimPlanetGrid::Y_IDX] = thePolarLat + latT*(90.0-thePolarLat);
+ }
+ // south polar cap
+ else if(gridPoint.face() == 13)
+ {
+ double offset = 1.0;
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] > gridPoint.theXYZ[ossimPlanetGrid::Y_IDX])
+ {
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] >= 1.0)
+ {
+ xt = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ yt = gridPoint.theXYZ[ossimPlanetGrid::X_IDX] - .5;
+ offset += 1.0;
+ }
+ else
+ {
+ xt = 1.0 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ yt = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ offset+=2;
+ }
+ }
+ else
+ {
+ if(gridPoint.theXYZ[ossimPlanetGrid::X_IDX] + gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] < 1.0)
+ {
+ xt = gridPoint.theXYZ[ossimPlanetGrid::Y_IDX];
+ yt = 0.5 - gridPoint.theXYZ[ossimPlanetGrid::X_IDX];
+ offset -= 1.0;
+ }
+ else
+ {
+ yt = gridPoint.theXYZ[ossimPlanetGrid::Y_IDX] - 0.5;
+ }
+ }
+ if(!ossim::almostEqual((double)yt, (double)0.0))
+ {
+ xt = ((xt - 0.5)*.5)/yt + .5;
+ }
+ xt = (xt + offset) *0.25;
+ yt *=.5;
+ modelPoint.theXYZ[ossimPlanetGrid::X_IDX] = xt*360.0 - 180.0;
+ modelPoint.theXYZ[ossimPlanetGrid::Y_IDX] = yt*180.0 - 90;
+ double latT = (modelPoint.theXYZ[ossimPlanetGrid::Y_IDX] + 45.0)/45;
+ modelPoint.theXYZ[ossimPlanetGrid::Y_IDX] = -thePolarLat - latT*(-90+thePolarLat);
+ }
+ modelPoint.setZ(gridPoint.z());
+}
+
+void ossimPlanetAdjustableCubeGrid::modelToGlobalGrid(const ModelPoint& modelPoint,
+ GridPoint& gridPoint)const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ ossimPlanetCubeGrid2::modelToGlobalGrid(modelPoint, gridPoint);
+ return;
+ }
+ double shiftedX = ossim::clamp(modelPoint.x() + 180.0,
+ 0.0, 360.0);
+ // south polar region
+ if(modelPoint.y() >= thePolarLat)
+ {
+ gridPoint.setFace(12);
+ // map into 45 to 90
+ //
+ double adjustedModelY = 45 + 45*((modelPoint.y()-thePolarLat)/(.5*thePolarWidth));
+ ModelPoint adjustedModel(modelPoint.x(),
+ adjustedModelY,
+ modelPoint.z());
+ ossimPlanetCubeGrid2::modelToGlobalGrid(adjustedModel, gridPoint);
+ gridPoint.setFace(12);
+ }
+ // south polar region
+ else if(modelPoint.y() < -thePolarLat)
+ {
+ double adjustedModelY = -45.0+((modelPoint.y() + thePolarLat)/(thePolarWidth*.5))*45;
+ ModelPoint adjustedModel(modelPoint.x(),
+ adjustedModelY,
+ modelPoint.z());
+ ossimPlanetCubeGrid2::modelToGlobalGrid(adjustedModel, gridPoint);
+ gridPoint.setFace(13);
+ }
+ // north band
+ else if(modelPoint.y() > 45.0)
+ {
+ ossim_uint32 face = (ossim_uint32)ossim::clamp((shiftedX / 90),
+ 0.0, 4.0);
+ gridPoint.setX((shiftedX-face*90.0)/90.0);
+ gridPoint.setY((modelPoint.y()-45.0)/theUpperEquatorialBandLatDelta);
+ gridPoint.setFace(face+4);
+ }
+ // equatorial band
+ else if(modelPoint.y() >= -45.0)
+ {
+ ossim_uint32 face = ossim::clamp(((modelPoint.x()+180.0) / 90.0),
+ 0.0, 3.0);
+ gridPoint.setX((shiftedX-face*90.0)/90.0);
+ gridPoint.setY((45.0+modelPoint.y())/90.0);
+ gridPoint.setFace(face);
+ }
+ // south lat band
+ else if(modelPoint.y() < -45.0)
+ {
+ ossim_uint32 face = ossim::clamp((shiftedX / 90),
+ 0.0, 7.0);
+ gridPoint.setX((shiftedX-face*90.0)/90.0);
+ gridPoint.setY((45.0+modelPoint.y())/theUpperEquatorialBandLatDelta);
+ gridPoint.setFace(face+8);
+ }
+}
+
+void ossimPlanetAdjustableCubeGrid::widthHeightInModelSpace(const ossimPlanetTerrainTileId& tileId,
+ osg::Vec2d& deltaXY)const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ ossimPlanetCubeGrid2::widthHeightInModelSpace(tileId, deltaXY);
+ return;
+ }
+ GridBound b;
+
+ bounds(tileId, b);
+
+ ossim_float64 multiplierx = 90;
+ ossim_float64 multipliery = 90;
+
+ if(tileId.face() < 4)
+ {
+ // purposely left blank;
+ }
+ else if(tileId.face() < 12)
+ {
+
+ multiplierx = 90;
+ multipliery = theUpperEquatorialBandLatDelta;
+ }
+ else if((tileId.face() == 12)||
+ (tileId.face() == 13))
+ {
+ multiplierx = (90-thePolarLat)*2.0;
+ multipliery = multiplierx;
+ }
+ deltaXY[0] = multiplierx*b.width();
+ deltaXY[1] = multipliery*b.height();
+}
+
+bool ossimPlanetAdjustableCubeGrid::findGridBound(ossim_uint32 face,
+ const ModelPoint& minPoint,
+ const ModelPoint& maxPoint,
+ GridBound& bound,
+ ossim_uint32 numberOfPoints)const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ return ossimPlanetCubeGrid2::findGridBound(face, minPoint, maxPoint, bound, numberOfPoints);
+ }
+ ossimDrect modelClipBound;
+ ossimDrect modelBound(minPoint.x(), maxPoint.y(), maxPoint.x(), minPoint.y(), OSSIM_RIGHT_HANDED);
+ ossimDrect modelFaceBound;
+ double epsilon = 1e-12;
+
+ if(face < 4)
+ {
+ double originX = -180.0 + face*90.0;
+ modelFaceBound = ossimDrect(originX, 45-epsilon, originX + 90.0-epsilon, -45.0, OSSIM_RIGHT_HANDED);
+ }
+ else if(face < 8)
+ {
+ double originX = -180.0 + (face-4)*90.0;
+ modelFaceBound = ossimDrect(originX, thePolarLat-epsilon, originX + 90.0, 45, OSSIM_RIGHT_HANDED);
+ }
+ else if(face < 12)
+ {
+ double originX = -180.0 + (face-8)*90.0;
+ modelFaceBound = ossimDrect(originX, -45.0+epsilon, originX + 90.0, -thePolarLat, OSSIM_RIGHT_HANDED);
+ }
+ else if(face == 12)
+ {
+ modelFaceBound = ossimDrect(-180.0, 90.0, 180.0, thePolarLat, OSSIM_RIGHT_HANDED);
+ }
+ else if(face == 13)
+ {
+ modelFaceBound = ossimDrect(-180.0, -thePolarLat+epsilon, 180.0, -90.0, OSSIM_RIGHT_HANDED);
+ }
+ else
+ {
+ return false;
+ }
+ bool result = modelFaceBound.intersects(modelBound);
+ if(result)
+ {
+ modelClipBound = modelBound.clipToRect(modelFaceBound);
+ // std::cout << "modelClipBound " << modelClipBound << std::endl;
+ // 4 equatorial faces
+ if(face < 4)
+ {
+ bound.theMiny = (45.0 + modelClipBound.ll().y)/90.0;
+ bound.theMinx = ((180.0 +modelClipBound.ll().x)/90.0) - face;
+ bound.theWidth = (modelClipBound.ur().x-modelClipBound.ll().x)/90.0;
+ bound.theHeight = (modelClipBound.ur().y-modelClipBound.ll().y)/90.0;
+ }
+ // 4 upper band faces
+ else if(face < 8)
+ {
+ bound.theMiny = (modelClipBound.ll().y - 45)/theUpperEquatorialBandLatDelta;
+ bound.theMinx = (180.0 + modelClipBound.ll().x)/90 - (face-4);
+ bound.theWidth = (modelClipBound.ur().x-modelClipBound.ll().x)/90.0;
+ bound.theHeight = (modelClipBound.ur().y-modelClipBound.ll().y)/theUpperEquatorialBandLatDelta;
+ }
+ // 4 lower band faces
+ else if(face < 12)
+ {
+ bound.theMiny = (modelClipBound.ll().y + thePolarLat)/theUpperEquatorialBandLatDelta;
+ bound.theMinx = (180.0 + modelClipBound.ll().x)/90.0 - (face-8);
+ bound.theWidth = (modelClipBound.ur().x-modelClipBound.ll().x)/90.0;
+ bound.theHeight = (modelClipBound.ur().y-modelClipBound.ll().y)/theUpperEquatorialBandLatDelta;
+ }
+ // north and south polar faces
+ else if((face == 12)||
+ (face == 13))
+ {
+ std::vector<ossimDpt> gridPoints;
+ ossim_uint32 idxY = 0;
+ ossim_uint32 idxX = 0;
+ double deltaModelX = modelClipBound.ur().x-modelClipBound.ll().x;
+ double deltaModelY = modelClipBound.ur().y-modelClipBound.ll().y;
+ ossimDpt ll = modelClipBound.ll();
+
+ ossimPlanetGrid::GridPoint gridPoint;
+ for(idxY = 0; idxY <numberOfPoints; ++idxY)
+ {
+ for(idxX = 0; idxX < numberOfPoints; ++idxX)
+ {
+ double tx = (double)idxX/(numberOfPoints-1);
+ double ty = (double)idxY/(numberOfPoints-1);
+
+ ossimPlanetGrid::ModelPoint modelPoint(ll.x + deltaModelX*tx,
+ ll.y + deltaModelY*ty);
+ modelToGlobalGrid(modelPoint, gridPoint);
+ gridPoints.push_back(ossimDpt(gridPoint.x(), gridPoint.y()));
+ }
+ }
+ ossimDrect rect(gridPoints, OSSIM_RIGHT_HANDED);
+ bound.theMinx = rect.ll().x;
+ bound.theMiny = rect.ll().y;
+ bound.theWidth = (rect.ur().x-rect.ll().x);
+ bound.theHeight= (rect.ur().y-rect.ll().y);
+ bound.theFace = face;
+ }
+ bound.setFace(face);
+ }
+
+ // std::cout << "bound.theMinX = " << bound.theMinx << "\n"
+ // << "bound.theMinY = " << bound.theMiny << "\n";
+ return result;
+}
+
+ossim_uint32 ossimPlanetAdjustableCubeGrid::numberOfFaces()const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ return ossimPlanetCubeGrid2::numberOfFaces();
+ }
+ return 14;
+}
+
+bool ossimPlanetAdjustableCubeGrid::isPolar(const ossimPlanetTerrainTileId& id)const
+{
+ if(theCapLocation == LOW_CAP)
+ {
+ return ossimPlanetCubeGrid2::isPolar(id);
+ }
+ return ((id.face() == 12)||
+ (id.face() == 13));
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetGridUtility.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetGridUtility.cpp
new file mode 100644
index 0000000..5bd30eb
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetGridUtility.cpp
@@ -0,0 +1,526 @@
+#include "ossimPlanet/ossimPlanetGridUtility.h"
+#include <ossim/base/ossimCommon.h>
+#include <iostream>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include "ossimPlanet/mkUtils.h"
+
+
+
+ossim_uint64 ossimPlanetGridUtility::getId(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ ossim_uint64 w,h;
+ getNumberOfTilesWideHigh(w, h, level);
+ if(level == 0)
+ {
+ return ((ossim_uint64)row*w + (ossim_uint64)col);
+ }
+ ossim_uint64 shift = getTotalNumberOfTiles(level - 1);
+
+ return (shift + ((ossim_uint64)w*row +
+ (ossim_uint64)col));
+}
+
+void ossimPlanetGridUtility::getPixelScaleAsDegrees(double& dx,
+ double& dy,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ ossimUnitType pixelScaleUnits;
+ getPixelScale(dx, dy, pixelScaleUnits, level, row, col);
+
+ if(pixelScaleUnits != OSSIM_DEGREES)
+ {
+ ossimUnitConversionTool conversion(dx, pixelScaleUnits);
+ dx = conversion.getValue(OSSIM_DEGREES);
+ conversion.setValue(dy, pixelScaleUnits);
+ dy = conversion.getValue(OSSIM_DEGREES);
+ }
+}
+
+void ossimPlanetGridUtility::getPixelScaleAsMeters(double& dx,
+ double& dy,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ ossimUnitType pixelScaleUnits;
+ getPixelScale(dx, dy, pixelScaleUnits, level, row, col);
+
+ if(pixelScaleUnits != OSSIM_METERS)
+ {
+ ossimUnitConversionTool conversion(dx, pixelScaleUnits);
+ dx = conversion.getValue(OSSIM_METERS);
+ conversion.setValue(dy, pixelScaleUnits);
+ dy = conversion.getValue(OSSIM_METERS);
+ }
+}
+
+void ossimPlanetGridUtility::mapToRowCol(ossim_uint64& targetRow,
+ ossim_uint64& targetCol,
+ ossim_uint32 targetLevel,
+ ossim_uint32 srcLevel,
+ ossim_uint64 srcRow,
+ ossim_uint64 srcCol)const
+{
+ if(targetLevel > srcLevel)
+ {
+ ossim_uint32 diff = targetLevel-srcLevel;
+ targetRow = srcRow<<diff;
+ targetCol = srcCol<<diff;
+ }
+ else if(targetLevel < srcLevel)
+ {
+ ossim_uint32 diff = srcLevel-targetLevel;
+ targetRow = srcRow>>diff;
+ targetCol = srcCol>>diff;
+ }
+ else
+ {
+ targetRow = srcRow;
+ targetCol = srcCol;
+ }
+}
+
+void ossimPlanetGridUtility::getGeographicLonCrossings(std::vector<osg::Vec2d>& minMaxPairs,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ if(!crossesGeographicBounds(level, row, col))
+ {
+ double minLat, minLon, maxLat, maxLon;
+ getLatLonBounds(minLat, minLon, maxLat, maxLon, level, row, col);
+ minMaxPairs.push_back(osg::Vec2d(minLon, maxLon));
+ }
+ else
+ {
+ osg::Vec3d ul, ur, lr, ll;
+ getLatLonCorners(ul, ur, lr, ll, level, row, col);
+ osg::Vec2d pt;
+ pt[0] = -180.0;
+ pt[1] = -180.0;
+ if(ul[ossimPlanetGridUtility::LON] < FLT_EPSILON)
+ {
+ if(ul[ossimPlanetGridUtility::LON] > pt[1])
+ {
+ pt[1] = ul[ossimPlanetGridUtility::LON];
+ }
+ }
+ if(ur[ossimPlanetGridUtility::LON] < FLT_EPSILON)
+ {
+ if(ur[ossimPlanetGridUtility::LON] > pt[1])
+ {
+ pt[1] = ur[ossimPlanetGridUtility::LON];
+ }
+ }
+ if(lr[ossimPlanetGridUtility::LON] < FLT_EPSILON)
+ {
+ if(lr[ossimPlanetGridUtility::LON] > pt[1])
+ {
+ pt[1] = lr[ossimPlanetGridUtility::LON];
+ }
+ }
+ if(ll[ossimPlanetGridUtility::LON] < FLT_EPSILON)
+ {
+ if(ll[ossimPlanetGridUtility::LON] > pt[1])
+ {
+ pt[1] = ll[ossimPlanetGridUtility::LON];
+ }
+ }
+ minMaxPairs.push_back(pt);
+
+ pt[0] = 180.0;
+ pt[1] = 180.0;
+ if(ul[ossimPlanetGridUtility::LON] > -FLT_EPSILON)
+ {
+ if(ul[ossimPlanetGridUtility::LON] < pt[0])
+ {
+ pt[0] = ul[ossimPlanetGridUtility::LON];
+ }
+ }
+ if(ur[ossimPlanetGridUtility::LON] > -FLT_EPSILON)
+ {
+ if(ur[ossimPlanetGridUtility::LON] < pt[0])
+ {
+ pt[0] = ur[ossimPlanetGridUtility::LON];
+ }
+ }
+ if(lr[ossimPlanetGridUtility::LON] > -FLT_EPSILON)
+ {
+ if(lr[ossimPlanetGridUtility::LON] < pt[0])
+ {
+ pt[0] = lr[ossimPlanetGridUtility::LON];
+ }
+ }
+ if(ll[ossimPlanetGridUtility::LON] > -FLT_EPSILON)
+ {
+ if(ll[ossimPlanetGridUtility::LON] < pt[0])
+ {
+ pt[0] = ll[ossimPlanetGridUtility::LON];
+ }
+ }
+ minMaxPairs.push_back(pt);
+ }
+}
+
+bool ossimPlanetGridUtility::crossesGeographicBounds(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ osg::Vec3d ul;
+ osg::Vec3d ur;
+ osg::Vec3d lr;
+ osg::Vec3d ll;
+
+ getLatLonCorners(ul, ur, lr, ll, level, row, col);
+
+ if((std::abs(ul[ossimPlanetGridUtility::LON]-ur[ossimPlanetGridUtility::LON])>180.0)||
+ (std::abs(ur[ossimPlanetGridUtility::LON]-lr[ossimPlanetGridUtility::LON])>180.0)||
+ (std::abs(lr[ossimPlanetGridUtility::LON]-ll[ossimPlanetGridUtility::LON])>180.0)||
+ (std::abs(ll[ossimPlanetGridUtility::LON]-ul[ossimPlanetGridUtility::LON])>180.0))
+ {
+ return true;
+ }
+// std::cout << "ul-ur = " << (ul[ossimPlanetGridUtility::LON]-ur[ossimPlanetGridUtility::LON]) << std::endl;
+// std::cout << "ur-lr = " << (ur[ossimPlanetGridUtility::LON]-lr[ossimPlanetGridUtility::LON]) << std::endl;
+// std::cout << "lr-ll = " << (lr[ossimPlanetGridUtility::LON]-ll[ossimPlanetGridUtility::LON]) << std::endl;
+// std::cout << "ll-ul = " << (ll[ossimPlanetGridUtility::LON]-ul[ossimPlanetGridUtility::LON]) << std::endl;
+// if((std::abs(ul[ossimPlanetGridUtility::LON] -
+// ur[ossimPlanetGridUtility::LON]) > 200.0)||
+// (std::abs(ur[ossimPlanetGridUtility::LON] -
+// lr[ossimPlanetGridUtility::LON]) > 200.0)||
+// (std::abs(lr[ossimPlanetGridUtility::LON] -
+// ll[ossimPlanetGridUtility::LON]) > 200.0)||
+// (std::abs(ll[ossimPlanetGridUtility::LON] -
+// ul[ossimPlanetGridUtility::LON]) > 200.0))
+// {
+// return true;
+// }
+
+ return false;
+}
+
+void ossimPlanetGridUtility::getWidthHeightInDegrees(double& deltaX,
+ double& deltaY,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+
+ osg::Vec3d ul;
+ osg::Vec3d ur;
+ osg::Vec3d lr;
+ osg::Vec3d ll;
+
+ getLatLonCorners(ul, ur, lr, ll, level, row, col);
+ ul[2] = 0;
+ ur[2] = 0;
+ lr[2] = 0;
+ ll[2] = 0;
+ deltaX = ossim::max((ul-ur).length(), (ll-lr).length());
+ deltaY = ossim::max((ul-ll).length(), (ur-lr).length());
+}
+
+void ossimPlanetGridUtility::getLatLonCorners(osg::Vec3d& ul,
+ osg::Vec3d& ur,
+ osg::Vec3d& lr,
+ osg::Vec3d& ll,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const
+{
+ ossimPlanetGridUtility::GridPoint gPoint;
+ getCenterGridPoint(gPoint,
+ level, row, col);
+ const osg::Vec3d& gridPoint = gPoint.theGlobalGridPoint;
+ ossimPlanetGridUtility::GridPoint p(gPoint);
+ double xSpacing, ySpacing;
+ getGridSpacing(xSpacing, ySpacing, level, row, col);
+
+ double xHalf = xSpacing*.5;
+ double yHalf = ySpacing*.5;
+ p.theGlobalGridPoint = osg::Vec3d(gridPoint[ossimPlanetGridUtility::LAT] - yHalf,
+ gridPoint[ossimPlanetGridUtility::LON] - xHalf,
+ gridPoint[ossimPlanetGridUtility::HGT]);
+ getLatLon(ul,
+ p);
+
+ p.theGlobalGridPoint = osg::Vec3d(gridPoint[ossimPlanetGridUtility::LAT] + yHalf,
+ gridPoint[ossimPlanetGridUtility::LON] - xHalf,
+ gridPoint[ossimPlanetGridUtility::HGT]);
+ getLatLon(ur,
+ p);
+
+ p.theGlobalGridPoint = osg::Vec3d(gridPoint[ossimPlanetGridUtility::LAT] + yHalf,
+ gridPoint[ossimPlanetGridUtility::LON] + xHalf,
+ gridPoint[ossimPlanetGridUtility::HGT]);
+ getLatLon(lr,
+ p);
+
+ p.theGlobalGridPoint = osg::Vec3d(gridPoint[ossimPlanetGridUtility::LAT] - yHalf,
+ gridPoint[ossimPlanetGridUtility::LON] + xHalf,
+ gridPoint[ossimPlanetGridUtility::HGT]);
+ getLatLon(ll,
+ p);
+}
+
+void ossimPlanetGridUtility::getCenterLatLon(osg::Vec3d& center,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const
+{
+ ossimPlanetGridUtility::GridPoint centerPoint;
+ getCenterGridPoint(centerPoint,
+ level,
+ row,
+ col);
+ getLatLon(center,
+ centerPoint);
+}
+
+
+void ossimPlanetGridUtility::getLatLonBounds(double& minLat,
+ double& minLon,
+ double& maxLat,
+ double& maxLon,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ createGridPoints(points,
+ level,
+ row,
+ col,
+ 3,
+ 3);
+ minLat = 90.0;
+ maxLat = -90.0;
+ minLon = 180.0;
+ maxLon = -180.0;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = points.size();
+ osg::Vec3d latLon;
+ for(idx = 0; idx < size; ++idx)
+ {
+ getLatLon(latLon, points[idx]);
+ minLat = ossim::min(minLat, latLon[ossimPlanetGridUtility::LAT]);
+ minLon = ossim::min(minLon, latLon[ossimPlanetGridUtility::LON]);
+ maxLat = ossim::max(maxLat, latLon[ossimPlanetGridUtility::LAT]);
+ maxLon = ossim::max(maxLon, latLon[ossimPlanetGridUtility::LON]);
+ }
+// ossimPlanetGridUtility::GridPoint centerPoint;
+// osg::Vec3d ul;
+// osg::Vec3d ur;
+// osg::Vec3d lr;
+// osg::Vec3d ll;
+// osg::Vec3d center=ul;
+// ossimPlanetGridUtility::GridPoint point;
+// getCenterGridPoint(centerPoint, level, row, col);
+// getLatLon(center, centerPoint);
+// getLatLonCorners(ul, ur, lr, ll, level, row, col);
+// minLat = ossim::min(center[0], ossim::min(ll[0], ossim::min(lr[0], ossim::min(ul[0], ur[0]))));
+// maxLat = ossim::max(center[0], ossim::max(ll[0], ossim::max(lr[0], ossim::max(ul[0], ur[0]))));
+// minLon = ossim::min(center[1], ossim::min(ll[1], ossim::min(lr[1], ossim::min(ul[1], ur[1]))));
+// maxLon = ossim::max(center[1], ossim::max(ll[1], ossim::max(lr[1], ossim::max(ul[1], ur[1]))));
+
+}
+
+void ossimPlanetGridUtility::getCenterGridPoint(ossimPlanetGridUtility::GridPoint& point,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const
+{
+ ossim_uint64 localRow; // local to the face
+ ossim_uint64 localCol;
+ ossim_uint64 wide;
+ ossim_uint64 high;
+ double xSpacing, ySpacing;
+ getNumberOfTilesWideHighPerFace(wide, high, level);
+ getGridSpacing(xSpacing, ySpacing, level, row, col);
+ getLocalRowColumn(localRow, localCol,
+ level, row, col);
+
+ point.theLocalGridPoint[ossimPlanetGridUtility::GRIDX] = .5;
+ point.theLocalGridPoint[ossimPlanetGridUtility::GRIDY] = .5;
+ point.theLocalGridPoint[ossimPlanetGridUtility::GRIDZ] = 0;
+ point.theFace = getFace(level, row, col);
+
+ point.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = ((double)localCol/(double)wide) + (xSpacing*.5);
+ point.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = ((double)localRow/(double)high) + (ySpacing*.5);
+ point.theGlobalGridPoint[ossimPlanetGridUtility::GRIDZ] = 0.0;
+}
+
+void ossimPlanetGridUtility::getCenterGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ ossim_uint32 level,
+ const osg::Vec3d& latLon)const
+{
+ ossim_uint64 tilesWide, tilesHigh;
+ getGridPoint(gridPoint, latLon);
+ getNumberOfTilesWideHighPerFace(tilesWide, tilesHigh, level);
+ double normWide = 1.0/tilesWide;
+ double normHigh = 1.0/tilesHigh;
+
+ ossim_uint32 col = (ossim_uint32)(gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX]/normWide);
+ ossim_uint32 row = (ossim_uint32)(gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY]/normHigh);
+
+ getCenterGridPoint(gridPoint,
+ level,
+ row,
+ col);
+}
+
+void ossimPlanetGridUtility::createGridPoints(std::vector<ossimPlanetGridUtility::GridPoint>& points,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ ossim_uint32 rows,
+ ossim_uint32 cols)const
+{
+ ossim_uint64 wide;
+ ossim_uint64 high;
+ ossim_uint64 localRow;
+ ossim_uint64 localCol;
+ ossim_uint32 face = getFace(level, row, col);
+ ossim_uint32 idx=0;
+ ossim_uint32 rowIdx = 0;
+ ossim_uint32 colIdx = 0;
+ getLocalRowColumn(localRow, localCol,
+ level, row, col);
+ getNumberOfTilesWideHighPerFace(wide, high, level);
+
+ ossim_float64 globalColTOrigin = (double)localCol/(double)(wide);
+ ossim_float64 globalRowTOrigin = (double)localRow/(double)(high);
+ ossim_float64 spacingCol = (1.0/(double)wide)/(cols-1);
+ ossim_float64 spacingRow = (1.0/(double)high)/(rows-1);
+ ossim_uint32 size = (rows)*(cols);
+ if(points.size() != size)
+ {
+ points.resize(size);
+ }
+ ossimPlanetGridUtility::GridPoint* pointList = &points.front();
+
+ double rowT = globalRowTOrigin;
+ for(rowIdx = 0; rowIdx < rows; ++rowIdx)
+ {
+ double localRowT = ((double)rowIdx/((double)rows-1));
+ double colT = globalColTOrigin;
+ for(colIdx = 0; colIdx < cols; ++colIdx)
+ {
+ pointList[idx].theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = colT;
+ pointList[idx].theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = rowT;
+ pointList[idx].theGlobalGridPoint[ossimPlanetGridUtility::GRIDZ] = 0.0;
+
+ pointList[idx].theLocalGridPoint[ossimPlanetGridUtility::GRIDX] = (double)colIdx/((double)cols-1.0);
+ pointList[idx].theLocalGridPoint[ossimPlanetGridUtility::GRIDY] = localRowT;
+ pointList[idx].theLocalGridPoint[ossimPlanetGridUtility::GRIDZ] = 0.0;
+
+ pointList[idx].theFace = face;
+ ++idx;
+ colT += spacingCol;
+ }
+ rowT += spacingRow;
+ }
+}
+
+void ossimPlanetGridUtility::getGridSpacing(double& xSpacing,
+ double& ySpacing,
+ ossim_uint32 level,
+ ossim_uint64 /*row*/,
+ ossim_uint64 /*col*/)const
+{
+ ossim_uint64 wide;
+ ossim_uint64 high;
+ getNumberOfTilesWideHighPerFace(wide, high, level);
+ xSpacing = 1.0/(double)wide;
+ ySpacing = 1.0/(double)high;
+
+}
+
+void ossimPlanetGridUtility::getNumberOfTilesWideHigh(ossim_uint64 &wide,
+ ossim_uint64 &high,
+ ossim_uint32 level)const
+{
+ wide = (ossim_uint64)1<<(ossim_uint64)level;
+ high = (ossim_uint64)1<<(ossim_uint64)level;
+
+ wide*=getNumberOfFaces();
+}
+
+void ossimPlanetGridUtility::getLocalRowColumn(ossim_uint64& localRow,
+ ossim_uint64& localCol,
+ ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ ossim_uint64 wide;
+ ossim_uint64 high;
+ getNumberOfTilesWideHighPerFace(wide, high, level);
+ ossim_uint32 face = getFace(level, row, col);
+
+ localRow = row;
+ localCol = col - face*wide;
+}
+
+ossim_uint32 ossimPlanetGridUtility::getFace(ossim_uint32 level,
+ ossim_uint64 /*row*/,
+ ossim_uint64 col)const
+{
+ return (col >> level);
+
+}
+
+void ossimPlanetGridUtility::getNumberOfTilesWideHighPerFace(ossim_uint64 &wide,
+ ossim_uint64 &high,
+ ossim_uint32 level)const
+{
+ wide = (ossim_uint64)1<<(ossim_uint64)level;
+ high = (ossim_uint64)1<<(ossim_uint64)level;
+}
+
+ossim_uint64 ossimPlanetGridUtility::getNumberOfTiles(ossim_uint32 level)const
+{
+ ossim_uint64 wide;
+ ossim_uint64 high;
+
+ getNumberOfTilesWideHigh(wide, high, level);
+
+ return ((ossim_uint64)wide * (ossim_uint64)high);
+}
+
+
+ossim_uint64 ossimPlanetGridUtility::getTotalNumberOfTiles(ossim_uint32 level)const
+{
+ ossim_uint64 result = 0;
+ ossim_uint32 idx=0;
+
+ for(idx = 0; idx <= level; ++idx)
+ {
+ result += getNumberOfTiles(idx);
+ }
+
+ return result;
+}
+
+
+ossim_uint32 ossimPlanetGridUtility::getTileWidth()const
+{
+ return theTileWidth;
+}
+
+ossim_uint32 ossimPlanetGridUtility::getTileHeight()const
+{
+ return theTileHeight;
+}
+
+void ossimPlanetGridUtility::setTileWidthHeight(ossim_uint32 tileWidth,
+ ossim_uint32 tileHeight)
+{
+ theTileWidth = tileWidth;
+ theTileHeight = tileHeight;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetIconGeom.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetIconGeom.cpp
new file mode 100644
index 0000000..0988738
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetIconGeom.cpp
@@ -0,0 +1,157 @@
+#include <ossimPlanet/ossimPlanetIconGeom.h>
+#include <iostream>
+
+ossimPlanetIconGeom::ossimPlanetIconGeom( const osg::Vec3d& corner,
+ const osg::Vec3d& width,
+ const osg::Vec3d& height)
+{
+ setUseDisplayList(false);
+ setupGeom(corner, width, height);
+ theAlpha = 1.0;
+}
+
+void ossimPlanetIconGeom::setTexture(osg::ref_ptr<osg::Image> img)
+{
+ if(!theTexture.valid())
+ {
+ theTexture = new osg::Texture2D;
+ theTexture->setResizeNonPowerOfTwoHint(false);
+ theTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
+ theTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
+ }
+ theTexture->setImage(img.get());
+}
+
+void ossimPlanetIconGeom::setTexture(osg::ref_ptr<osg::Texture2D> texture)
+{
+ theTexture = texture.get();
+ getOrCreateStateSet()->setTextureAttributeAndModes(0,theTexture.get(),osg::StateAttribute::ON);
+}
+
+void ossimPlanetIconGeom::resetToUnitGeometry()
+{
+ setGeometry(osg::Vec3d(-.5,0.0,-.5),
+ osg::Vec3d(1.0,0.0,0.0),
+ osg::Vec3d(0.0,0.0,1.0));
+}
+
+
+void ossimPlanetIconGeom::setGeometry(const osg::Vec3d& corner,
+ const osg::Vec3d& width,
+ const osg::Vec3d& height)
+{
+ osg::ref_ptr<osg::Vec3dArray> coords = dynamic_cast<osg::Vec3dArray*>(getVertexArray());
+ if(coords.valid())
+ {
+ (*coords)[0] = corner;
+ (*coords)[1] = corner+width;
+ (*coords)[2] = corner+width+height;
+ (*coords)[3] = corner+height;
+ setVertexArray(coords.get());
+ }
+ osg::ref_ptr<osg::Vec3Array> norms = dynamic_cast<osg::Vec3Array*>(getNormalArray());
+ if(norms.valid())
+ {
+ (*norms)[0] = width^height;
+ (*norms)[0].normalize();
+ setNormalArray(norms.get());
+ }
+}
+
+void ossimPlanetIconGeom::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+ osg::Vec4 save = (*theColorArray)[0];
+ (*theColorArray)[0][3] = theAlpha;
+ osg::Geometry::drawImplementation(renderInfo);
+ (*theColorArray)[0] = save;
+}
+
+void ossimPlanetIconGeom::setupGeom(const osg::Vec3d& corner,
+ const osg::Vec3d& width,
+ const osg::Vec3d& height)
+{
+ osg::Vec3dArray* coords = new osg::Vec3dArray(4);
+ (*coords)[0] = corner;
+ (*coords)[1] = corner+width;
+ (*coords)[2] = corner+width+height;
+ (*coords)[3] = corner+height;
+ setVertexArray(coords);
+
+ osg::Vec3dArray* norms = new osg::Vec3dArray(1);
+ (*norms)[0] = width^height;
+ (*norms)[0].normalize();
+
+ setNormalArray(norms);
+ setNormalBinding(osg::Geometry::BIND_OVERALL);
+ theColorArray = new osg::Vec4dArray;
+ theColorArray->push_back(osg::Vec4(1.0,
+ 1.0,
+ 1.0,
+ 1.0));
+ setColorBinding(osg::Geometry::BIND_OVERALL);
+ setColorArray(theColorArray.get());
+
+ osg::Vec2dArray* tcoords = new osg::Vec2dArray(4);
+ (*tcoords)[0].set(0.0,0.0);
+ (*tcoords)[1].set(1.0,0.0);
+ (*tcoords)[2].set(1.0,1.0);
+ (*tcoords)[3].set(0.0,1.0);
+ setTexCoordArray(0,tcoords);
+ addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
+ osg::StateSet* stateset = new osg::StateSet;
+ theTexture = new osg::Texture2D;
+ theTexture->setResizeNonPowerOfTwoHint(false);
+ stateset->setTextureAttributeAndModes(0,theTexture.get(),osg::StateAttribute::ON);
+ setStateSet(stateset);
+}
+
+void ossimPlanetIconGeom::setTextureCoordinatesGivenPixels(int originX,
+ int originY,
+ int pixelWidth,
+ int pixelHeight)
+{
+ if(theTexture.valid())
+ {
+ float w = theTexture->getTextureWidth();
+ float h = theTexture->getTextureHeight();
+ osg::ref_ptr<osg::Vec2Array> tcoords = dynamic_cast<osg::Vec2Array*>(getVertexArray());
+ float cornertx = (float)originX/w;
+ float cornerty = (float)originY/h;
+
+ (*tcoords)[0].set(cornertx, cornerty);
+ (*tcoords)[1].set(cornertx+pixelWidth/w, cornerty);
+ (*tcoords)[2].set(cornertx+pixelWidth/w, cornerty+pixelHeight/h);
+ (*tcoords)[3].set(cornertx, cornerty+pixelHeight/h);
+ dirtyBound();
+ }
+}
+
+ossim_uint32 ossimPlanetIconGeom::width()const
+{
+ if(theTexture.valid())
+ {
+ theTexture->getTextureWidth();
+ }
+ return 0;
+}
+
+ossim_uint32 ossimPlanetIconGeom::height()const
+{
+ if(theTexture.valid())
+ {
+ theTexture->getTextureHeight();
+ }
+
+ return 0;
+}
+
+
+osg::ref_ptr<osg::Texture2D> ossimPlanetIconGeom::texture()
+{
+ return theTexture;
+}
+
+const osg::ref_ptr<osg::Texture2D> ossimPlanetIconGeom::texture()const
+{
+ return theTexture;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetId.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetId.cpp
new file mode 100644
index 0000000..42104bd
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetId.cpp
@@ -0,0 +1,8 @@
+#include <ossimPlanet/ossimPlanetId.h>
+
+ossim_int64 ossimPlanetId::theInvalidId = -1;
+
+ossim_int64 ossimPlanetId::invalidId()
+{
+ return theInvalidId;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetIdManager.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetIdManager.cpp
new file mode 100644
index 0000000..6684896
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetIdManager.cpp
@@ -0,0 +1,12 @@
+#include <ossimPlanet/ossimPlanetIdManager.h>
+#include <OpenThreads/ScopedLock>
+
+ossimPlanetId ossimPlanetIdManager::theCurrentId = 0;
+ossimPlanetReentrantMutex ossimPlanetIdManager::theMutex;
+
+ossimPlanetId ossimPlanetIdManager::nextId()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ return ++theCurrentId;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetImage.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetImage.cpp
new file mode 100644
index 0000000..8499993
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetImage.cpp
@@ -0,0 +1,1157 @@
+#include <iostream>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <OpenThreads/ScopedLock>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimHsiVector.h>
+#include <ossim/base/ossimRgbVector.h>
+#include <osgDB/ReadFile>
+//#define OSGPLANET_ENABLE_ALLOCATION_COUNT
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static ossim_uint32 imageCount = 0;
+#endif
+
+ossimPlanetImage::ossimPlanetImage()
+:osg::Image(),
+theState(ossimPlanetImageStateType_NONE),
+thePixelStatus(ossimPlanetImagePixelStatus_EMPTY),
+thePadding(0)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++imageCount;
+ std::cout << "ossimPlanetImage2D count = " << imageCount << std::endl;
+#endif
+}
+
+ossimPlanetImage::ossimPlanetImage(const osg::Image& src)
+:osg::Image(src),
+theState(ossimPlanetImageStateType_NONE),
+thePixelStatus(ossimPlanetImagePixelStatus_EMPTY),
+thePadding(0)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++imageCount;
+ std::cout << "ossimPlanetImage2D count = " << imageCount << std::endl;
+#endif
+}
+
+ossimPlanetImage::ossimPlanetImage(const ossimPlanetTerrainTileId& id)
+:osg::Image(),
+theState(ossimPlanetImageStateType_NONE),
+theTileId(id),
+thePixelStatus(ossimPlanetImagePixelStatus_EMPTY),
+thePadding(0)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++imageCount;
+ std::cout << "ossimPlanetImage2D count = " << imageCount << std::endl;
+#endif
+}
+
+ossimPlanetImage::ossimPlanetImage(const ossimPlanetImage& image,
+const osg::CopyOp& copyop)
+:osg::Image(image,copyop),
+theState(image.theState),
+theTileId(image.theTileId),
+thePixelStatus(image.thePixelStatus),
+theMinValue(image.theMinValue),
+theMaxValue(image.theMaxValue),
+thePadding(image.thePadding)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++imageCount;
+ std::cout << "ossimPlanetImage2D count = " << imageCount << std::endl;
+#endif
+}
+
+ossimPlanetImage::~ossimPlanetImage()
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ --imageCount;
+ std::cout << "ossimPlanetImage2D count = " << imageCount << std::endl;
+#endif
+}
+
+void ossimPlanetImage::stripPadding()
+{
+ if(padding() > 0)
+ {
+ osg::ref_ptr<ossimPlanetImage> tempImage = new ossimPlanetImage(*this);
+ allocateImage(widthWithoutPadding(),
+ heightWithoutPadding(),
+ 1,
+ getPixelFormat(),
+ getDataType(),
+ getPacking());
+ setPadding(0);
+ tempImage->copyTo(tempImage->padding(), tempImage->padding(), this);
+ }
+}
+
+int ossimPlanetImage::getNumberOfComponents()const
+{
+ return computeNumComponents(getPixelFormat());
+}
+
+int ossimPlanetImage::getHeight()const
+{
+ return t();
+}
+
+int ossimPlanetImage::getWidth()const
+{
+ return s();
+}
+
+void ossimPlanetImage::setId(const ossimPlanetTerrainTileId& id)
+{
+ theTileId = id;
+}
+
+const ossimPlanetTerrainTileId& ossimPlanetImage::tileId()const
+{
+ return theTileId;
+}
+
+ossimPlanetImage::ossimPlanetImageStateType ossimPlanetImage::getState()const
+{
+ return theState;
+}
+
+void ossimPlanetImage::setState(ossimPlanetImageStateType stateType)
+{
+ theState = stateType;
+}
+
+OpenThreads::Mutex& ossimPlanetImage::mutex()const
+{
+ return theMutex;
+}
+
+void ossimPlanetImage::setPixelStatus()
+{
+ GLint internalFormat = getInternalTextureFormat();
+ switch(internalFormat)
+ {
+ case GL_RGBA:
+ {
+ unsigned char* dataPtr = data();
+ unsigned int w = s();
+ unsigned int h = t();
+ unsigned int area = w*h;
+ thePixelStatus = ossimPlanetImagePixelStatus_FULL;
+ bool hasFull = false;
+ bool hasTranslucent = false;
+ bool hasTransparent = false;
+ if(!dataPtr) return;
+
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ if(dataPtr[3] == 0)
+ {
+ hasTransparent = true;
+ }
+ if(dataPtr[3] == 255)
+ {
+ hasFull = true;
+ }
+ else
+ {
+ hasTranslucent = true;
+ }
+ if((hasTranslucent) ||
+ (hasFull&&hasTransparent))
+ {
+ break;
+ }
+ dataPtr+=4;
+ }
+ if(hasTranslucent)
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_PARTIAL;
+ }
+ else if(hasTransparent&&hasFull)
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_PARTIAL;
+ }
+ else if(hasTransparent)
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_EMPTY;
+ }
+ else if(hasFull)
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_FULL;
+ }
+ break;
+ }
+ default:
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_FULL;
+ }
+ }
+}
+
+void ossimPlanetImage::setPixelStatus(ossimPlanetImagePixelStatus pixelStatus)
+{
+ thePixelStatus = pixelStatus;
+}
+
+ossimPlanetImage::ossimPlanetImagePixelStatus ossimPlanetImage::getPixelStatus()const
+{
+ return thePixelStatus;
+}
+
+void ossimPlanetImage::applyBrightnessContrast(ossim_float32 brightness, ossim_float32 contrast)
+{
+ GLint internalFormat = getInternalTextureFormat();
+ ossim_uint32 width = s();
+ ossim_uint32 height = t();
+ ossim_uint32 inputBands = 4;
+ switch(internalFormat)
+ {
+ case GL_RGBA:
+ {
+ ossim_float32 normBrightness = brightness/255.0;
+ ossim_uint8* inputPtr = (ossim_uint8*)data();
+ ossim_uint32 size = width*height;
+ ossim_uint32 idx = 0;
+ inputBands = 4;
+ for(;idx < size; ++idx)
+ {
+ if(inputPtr[3] > 0.0)
+ {
+ ossimHsiVector hsi(ossimRgbVector(inputPtr[0], inputPtr[1], inputPtr[2]));
+
+ ossim_float32 i = hsi.getI()*contrast + normBrightness;
+ // i = ossim::clamp(i, OSSIM_DEFAULT_MIN_PIX_NORM_FLOAT, 1.0f);
+ i = ossim::clamp(i, 0.0f, 1.0f);
+ hsi.setI(i);
+ ossimRgbVector newRgb(hsi);
+ inputPtr[0] = newRgb.getR();
+ inputPtr[1] = newRgb.getG();
+ inputPtr[2] = newRgb.getB();
+ }
+ inputPtr+=inputBands;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+ossimRefPtr<ossimImageData> ossimPlanetImage::toOssimImage()const
+{
+ ossimRefPtr<ossimImageData> imageData;
+ GLint internalFormat = getInternalTextureFormat();
+ ossim_uint32 inputBands = 3;
+ if(internalFormat == GL_RGBA)
+ {
+ inputBands = 4;
+ }
+
+ if(!data()) return 0;
+ ossim_uint32 width = s();
+ ossim_uint32 height = t();
+
+ switch(internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ {
+ if((internalFormat == GL_RGB)||
+ (internalFormat == GL_RGBA))
+ {
+ imageData = new ossimImageData(0,
+ OSSIM_UINT8,
+ 3,
+ width,
+ height);
+ imageData->initialize();
+ const ossim_uint8* inputPtr = (const ossim_uint8*)data();
+ ossim_uint8* outputPtr[3];
+ outputPtr[0] = (ossim_uint8*)(imageData->getBuf(0));
+ outputPtr[1] = (ossim_uint8*)(imageData->getBuf(1));
+ outputPtr[2] = (ossim_uint8*)(imageData->getBuf(2));
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = width*height;
+ if(internalFormat != GL_RGBA)
+ {
+ for(idx =0; idx < size; ++idx)
+ {
+ outputPtr[0][idx] = inputPtr[0];
+ outputPtr[1][idx] = inputPtr[1];
+ outputPtr[2][idx] = inputPtr[2];
+ inputPtr+=inputBands;
+ }
+ }
+ else
+ {
+ for(idx =0; idx < size; ++idx)
+ {
+ if(inputPtr[3] == 0)
+ {
+ outputPtr[0][idx] = 0;
+ outputPtr[1][idx] = 0;
+ outputPtr[2][idx] = 0;
+
+ }
+ else
+ {
+ outputPtr[0][idx] = inputPtr[0];
+ outputPtr[1][idx] = inputPtr[1];
+ outputPtr[2][idx] = inputPtr[2];
+ }
+ inputPtr+=inputBands;
+ }
+ }
+ imageData->validate();
+ }
+ break;
+ }
+ case GL_LUMINANCE:
+ {
+ if(getDataType() == GL_FLOAT)
+ {
+ imageData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width,
+ height);
+ imageData->initialize();
+ const ossim_float32* inputPtr = (const ossim_float32*)data();
+ ossim_float32* outputPtr = (ossim_float32*)imageData->getBuf();
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = width*height;
+ for(idx =0; idx < size; ++idx)
+ {
+ *outputPtr = *inputPtr;
+ ++inputPtr;
+ ++outputPtr;
+ }
+ imageData->setDataObjectStatus(OSSIM_FULL);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+
+ return imageData;
+}
+
+void ossimPlanetImage::fromOssimImage(ossimRefPtr<ossimImageData> data,
+ bool reassignNullFlag,
+ double nullValue)
+{
+ ossim_uint32 w = 0;
+ ossim_uint32 h = 0;
+ GLint internalFormat = GL_LUMINANCE;
+ GLenum pixelFormat = GL_LUMINANCE;
+ GLenum type = GL_FLOAT;
+ osg::Image::AllocationMode allocMode = osg::Image::USE_NEW_DELETE;
+ unsigned char* buf = 0;
+ ossim_uint32 validPixelCount = 0;
+ ossim_uint32 invalidPixelCount = 0;
+ if(data.valid())
+ {
+ w = data->getWidth();
+ h = data->getHeight();
+ switch(data->getScalarType())
+ {
+ case OSSIM_UINT8: // only support 1 to 3 band and will convert to RGBA gl type
+ {
+ if(data->getNumberOfBands()>0)
+ {
+ ossim_uint8 nullPix = (ossim_uint8)data->getNullPix(0);
+ ossim_uint32 sizeInBytes = data->getSizePerBandInBytes()*4;
+ buf = new unsigned char[sizeInBytes];
+ unsigned char* bufPtr = buf;
+
+
+ memset(buf, 0, sizeInBytes);
+
+ if(data->getBuf()&&
+ data->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ unsigned char* dataBuf[3];
+
+ dataBuf[0] = (unsigned char*)data->getBuf(0);
+ if(data->getNumberOfBands() > 1)
+ {
+ dataBuf[1] = (unsigned char*)data->getBuf(1);
+ }
+ else
+ {
+ dataBuf[1] = (unsigned char*)data->getBuf(0);
+ }
+ if(data->getNumberOfBands() > 2)
+ {
+ dataBuf[2] = (unsigned char*)data->getBuf(2);
+ }
+ else
+ {
+ dataBuf[2] = (unsigned char*)data->getBuf(0);
+ }
+ ossim_uint32 area = data->getWidth()*data->getHeight();
+ ossim_uint32 idx = 0;
+ for(;idx < area; ++idx)
+ {
+ if((*dataBuf[0] != nullPix)||
+ (*dataBuf[1] != nullPix)||
+ (*dataBuf[2] != nullPix))
+ {
+ bufPtr[0] = *dataBuf[0];
+ bufPtr[1] = *dataBuf[1];
+ bufPtr[2] = *dataBuf[2];
+ bufPtr[3] = 255;
+ ++validPixelCount;
+ }
+ else
+ {
+ ++invalidPixelCount;
+ bufPtr[3] = 0;
+ }
+ bufPtr+=4;
+ ++dataBuf[0];
+ ++dataBuf[1];
+ ++dataBuf[2];
+ }
+ if(invalidPixelCount > 0)
+ {
+ thePixelStatus = validPixelCount > 0?ossimPlanetImagePixelStatus_PARTIAL:ossimPlanetImagePixelStatus_EMPTY;
+ }
+ else
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_FULL;
+ }
+ }
+ else
+ {
+ thePixelStatus = ossimPlanetImagePixelStatus_EMPTY;
+ }
+ internalFormat = GL_RGBA;
+ pixelFormat = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ }
+ break;
+ }
+ case OSSIM_FLOAT32: // only support 1 band
+ {
+ ossim_float32* bufPtr = new ossim_float32[w*h];
+ buf = reinterpret_cast<unsigned char*>(bufPtr);
+
+ memset(buf, 0, w*h*sizeof(ossim_float32));
+
+ ossim_float32* dataBuf = (ossim_float32*)data->getBuf();
+ ossim_float32 nullPix = (ossim_float32)data->getNullPix(0);
+ ossim_float32 tempNullValue = nullValue;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = w*h;
+
+ if(dataBuf)
+ {
+ for(;idx < area; ++idx)
+ {
+ *bufPtr = *dataBuf;
+ if(reassignNullFlag)
+ {
+ if(nullPix == *dataBuf)
+ {
+ *bufPtr = tempNullValue;
+ }
+ }
+ ++bufPtr;
+ ++dataBuf;
+ }
+ }
+
+ break;
+ }
+ case OSSIM_SINT16: // only support 1 band
+ {
+ ossim_float32* bufPtr = new ossim_float32[w*h];
+ buf = reinterpret_cast<unsigned char*>(bufPtr);
+
+ memset(buf, 0, w*h*sizeof(ossim_float32));
+
+ ossim_sint16* dataBuf = (ossim_sint16*)data->getBuf();
+ ossim_sint16 nullPix = (ossim_sint16)data->getNullPix(0);
+ ossim_float32 tempNullValue = (ossim_float32)nullValue;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = w*h;
+
+ if(dataBuf)
+ {
+ for(;idx < area; ++idx)
+ {
+ *bufPtr = *dataBuf;
+ if(reassignNullFlag)
+ {
+ if(nullPix == *dataBuf)
+ {
+ *bufPtr = tempNullValue;
+ }
+ }
+ ++bufPtr;
+ ++dataBuf;
+ }
+ }
+ break;
+ }
+ case OSSIM_UINT16: // only support 1 band
+ case OSSIM_USHORT11: // only support 1 band
+ {
+ ossim_float32* bufPtr = new ossim_float32[w*h];
+ buf = reinterpret_cast<unsigned char*>(bufPtr);
+
+ memset(buf, 0, w*h*sizeof(ossim_float32));
+
+ ossim_uint16* dataBuf = (ossim_uint16*)data->getBuf();
+ ossim_uint16 nullPix = (ossim_uint16)data->getNullPix(0);
+ ossim_float32 tempNullValue = (ossim_float32)nullValue;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = w*h;
+
+ if(dataBuf)
+ {
+ for(;idx < area; ++idx)
+ {
+ *bufPtr = *dataBuf;
+ if(reassignNullFlag)
+ {
+ if(nullPix == *dataBuf)
+ {
+ *bufPtr = tempNullValue;
+ }
+ }
+ ++bufPtr;
+ ++dataBuf;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ // not supported yet
+ break;
+ }
+ }
+ }
+
+ if(buf)
+ {
+ setImage(w, h, 1, internalFormat, pixelFormat, type, buf, allocMode);
+ }
+}
+
+void ossimPlanetImage::fromOssimImageNoAlpha(ossimRefPtr<ossimImageData> data,
+ bool reassignNullFlag,
+ double nullValue)
+{
+ ossim_uint32 w = 0;
+ ossim_uint32 h = 0;
+ GLint internalFormat = GL_LUMINANCE;
+ GLenum pixelFormat = GL_LUMINANCE;
+ GLenum type = GL_FLOAT;
+ osg::Image::AllocationMode allocMode = osg::Image::USE_NEW_DELETE;
+ unsigned char* buf = 0;
+ if(data.valid())
+ {
+ w = data->getWidth();
+ h = data->getHeight();
+ switch(data->getScalarType())
+ {
+ case OSSIM_UINT8: // only support 1 to 3 band and will convert to RGBA gl type
+ {
+ if(data->getNumberOfBands()>0)
+ {
+ ossim_uint8 nullPix = (ossim_uint8)data->getNullPix(0);
+ ossim_uint32 sizeInBytes = data->getSizePerBandInBytes()*3;
+ buf = new unsigned char[sizeInBytes];
+ unsigned char* bufPtr = buf;
+
+
+ memset(buf, 0, sizeInBytes);
+
+ if(data->getBuf()&&
+ data->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ unsigned char* dataBuf[3];
+
+ dataBuf[0] = (unsigned char*)data->getBuf(0);
+ if(data->getNumberOfBands() > 1)
+ {
+ dataBuf[1] = (unsigned char*)data->getBuf(1);
+ }
+ else
+ {
+ dataBuf[1] = (unsigned char*)data->getBuf(0);
+ }
+ if(data->getNumberOfBands() > 2)
+ {
+ dataBuf[2] = (unsigned char*)data->getBuf(2);
+ }
+ else
+ {
+ dataBuf[2] = (unsigned char*)data->getBuf(0);
+ }
+ ossim_uint32 area = data->getWidth()*data->getHeight();
+ ossim_uint32 idx = 0;
+ for(;idx < area; ++idx)
+ {
+ if((*dataBuf[0] != nullPix)||
+ (*dataBuf[1] != nullPix)||
+ (*dataBuf[2] != nullPix))
+ {
+ bufPtr[0] = *dataBuf[0];
+ bufPtr[1] = *dataBuf[1];
+ bufPtr[2] = *dataBuf[2];
+ }
+ bufPtr+=3;
+ ++dataBuf[0];
+ ++dataBuf[1];
+ ++dataBuf[2];
+ }
+ internalFormat = GL_RGB;
+ pixelFormat = GL_RGB;
+ type = GL_UNSIGNED_BYTE;
+ }
+ }
+ break;
+ }
+ case OSSIM_FLOAT32: // only support 1 band
+ {
+ ossim_float32* bufPtr = new ossim_float32[w*h];
+ buf = reinterpret_cast<unsigned char*>(bufPtr);
+
+ memset(buf, 0, w*h*sizeof(ossim_float32));
+
+ ossim_float32* dataBuf = (ossim_float32*)data->getBuf();
+ ossim_float32 nullPix = (ossim_float32)data->getNullPix(0);
+ ossim_float32 tempNullValue = nullValue;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = w*h;
+
+ if(dataBuf)
+ {
+ for(;idx < area; ++idx)
+ {
+ *bufPtr = *dataBuf;
+ if(reassignNullFlag)
+ {
+ if(nullPix == *dataBuf)
+ {
+ *bufPtr = tempNullValue;
+ }
+ }
+ ++bufPtr;
+ ++dataBuf;
+ }
+ }
+
+ break;
+ }
+ case OSSIM_SINT16: // only support 1 band
+ {
+ ossim_float32* bufPtr = new ossim_float32[w*h];
+ buf = reinterpret_cast<unsigned char*>(bufPtr);
+
+ memset(buf, 0, w*h*sizeof(ossim_float32));
+
+ ossim_sint16* dataBuf = (ossim_sint16*)data->getBuf();
+ ossim_sint16 nullPix = (ossim_sint16)data->getNullPix(0);
+ ossim_float32 tempNullValue = (ossim_float32)nullValue;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = w*h;
+
+ if(dataBuf)
+ {
+ for(;idx < area; ++idx)
+ {
+ *bufPtr = *dataBuf;
+ if(reassignNullFlag)
+ {
+ if(nullPix == *dataBuf)
+ {
+ *bufPtr = tempNullValue;
+ }
+ }
+ ++bufPtr;
+ ++dataBuf;
+ }
+ }
+ break;
+ }
+ case OSSIM_UINT16: // only support 1 band
+ case OSSIM_USHORT11: // only support 1 band
+ {
+ ossim_float32* bufPtr = new ossim_float32[w*h];
+ buf = reinterpret_cast<unsigned char*>(bufPtr);
+
+ memset(buf, 0, w*h*sizeof(ossim_float32));
+
+ ossim_uint16* dataBuf = (ossim_uint16*)data->getBuf();
+ ossim_uint16 nullPix = (ossim_uint16)data->getNullPix(0);
+ ossim_float32 tempNullValue = (ossim_float32)nullValue;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = w*h;
+
+ if(dataBuf)
+ {
+ for(;idx < area; ++idx)
+ {
+ *bufPtr = *dataBuf;
+ if(reassignNullFlag)
+ {
+ if(nullPix == *dataBuf)
+ {
+ *bufPtr = tempNullValue;
+ }
+ }
+ ++bufPtr;
+ ++dataBuf;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ // not supported yet
+ break;
+ }
+ }
+ }
+
+ if(buf)
+ {
+ setImage(w, h, 1, internalFormat, pixelFormat, type, buf, allocMode);
+ }
+}
+
+osg::Image* ossimPlanetImage::readNewOsgImage(const ossimFilename& src,
+ bool flipVerticalFlag,
+ bool insertAlphaFlag)
+{
+ ossimRefPtr<ossimImageHandler> ih = ossimImageHandlerRegistry::instance()->open(ossimFilename(src));
+
+// if(!ih.valid()) return 0;
+// if(!ih.valid())
+// {
+// return osgDB::readImageFile(src);
+// }
+// else
+ if(ih.valid())
+ {
+ osg::ref_ptr<ossimPlanetImage> planetImage = new ossimPlanetImage;
+ ossimIrect rect = ih->getBoundingRect() ;
+ ossimRefPtr<ossimImageData> tile = ih->getTile(rect);
+ if(insertAlphaFlag)
+ {
+ planetImage->fromOssimImage(tile.get());
+ }
+ else
+ {
+ planetImage->fromOssimImageNoAlpha(tile.get());
+ }
+ if(flipVerticalFlag)
+ {
+ planetImage->flipVertical();
+ }
+ return new osg::Image(*(planetImage.get()), osg::CopyOp::DEEP_COPY_ALL);
+ }
+
+ return 0;
+}
+
+ossimPlanetImage* ossimPlanetImage::scaleImagePowerOf2()const
+{
+ GLint internalFormat = getInternalTextureFormat();
+// ossim_int32 oddW = getWidth()%2;
+// ossim_int32 oddH = getHeight()%2;
+ switch(internalFormat)
+ {
+ case GL_LUMINANCE:
+ {
+ if(getDataType() == GL_FLOAT)
+ {
+ return scaleImagePowerOf2((ossim_float32)0.0);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void ossimPlanetImage::copySubImageAndInsertPointsPowerOf2(int x, // starting x
+ int y, // starting y
+ ossim_uint32 lengthx, // length x
+ ossim_uint32 lengthy, // length y
+ ossimPlanetImage* source)
+{
+ if(!source||!source->data()||(_pixelFormat != source->getPixelFormat())||
+ (getDataType()!=source->getDataType()))
+ {
+ return;
+ }
+ GLint internalFormat = getInternalTextureFormat();
+
+ switch(internalFormat)
+ {
+ case GL_LUMINANCE:
+ {
+ if(getDataType() == GL_FLOAT)
+ {
+ copySubImageAndInsertPointsPowerOf2((ossim_float32)0,
+ x,
+ y,
+ lengthx,
+ lengthy,
+ source);
+ }
+ break;
+ }
+ }
+}
+
+void ossimPlanetImage::copyTo(ossim_uint32 x, ossim_uint32 y, ossimPlanetImage* destination)const
+{
+ if(!destination||!data()||(_pixelFormat != destination->getPixelFormat())||
+ (getDataType()!=destination->getDataType()))
+ {
+ return;
+ }
+ GLint internalFormat = getInternalTextureFormat();
+
+ switch(internalFormat)
+ {
+ case GL_LUMINANCE:
+ {
+ if(getDataType() == GL_FLOAT)
+ {
+ copyTo((ossim_float32)0,
+ x,
+ y,
+ destination);
+ }
+ break;
+ }
+ }
+}
+
+template<class T>
+void ossimPlanetImage::copyTo(T dummy, ossim_uint32 x, ossim_uint32 y, ossimPlanetImage* destination)const
+{
+ ossim_uint32 outW = destination->getWidth();
+ ossim_uint32 outH = destination->getHeight();
+ ossim_uint32 inW = getWidth();
+
+ T* destData = (T*)destination->data();
+ T* srcData = (T*)data();
+
+ srcData = srcData + inW*y + x;
+
+ ossim_uint32 xidx = 0;
+ ossim_uint32 yidx = 0;
+ for(yidx = 0; yidx < outH; ++yidx)
+ {
+ for(xidx = 0; xidx < outW; ++xidx)
+ {
+ destData[xidx] = srcData[xidx];
+ }
+ destData+=outW;
+ srcData += inW;
+ }
+ destination->setMinMax(minValue(), maxValue());
+}
+
+template<class T>
+ossimPlanetImage* ossimPlanetImage::scaleImagePowerOf2(T dummy)const
+{
+ ossimPlanetImage* result = new ossimPlanetImage(tileId());
+ result->setPadding(padding());
+ result->setMinMax(minValue(), maxValue());
+ result->setId(tileId());
+
+ // ossim_uint32 outW = widthWithoutPadding()*2+2*padding() - ((ossim_int32)widthWithoutPadding()%2);
+ // ossim_uint32 outH = heightWithoutPadding()*2+2*padding()- ((ossim_int32)heightWithoutPadding()%2);
+ ossim_uint32 outW = getWidth()*2 - ((ossim_int32)widthWithoutPadding()%2);
+ ossim_uint32 outH = getHeight()*2- ((ossim_int32)heightWithoutPadding()%2);
+ ossim_uint32 srcW = getWidth();
+// ossim_uint32 srcH = getHeight();
+ ossim_uint32 inOriginY = 0;//padding();
+ ossim_uint32 inOriginX = 0;//padding();
+ ossim_uint32 outOriginX = 0;//result->padding();
+ ossim_uint32 outOriginY = 0;//result->padding();
+ // we will interpolate the padding differently if padding exists
+// ossim_uint32 lengthX = outW - padding()*2; // now setup the bilinear interpolation length for x direction
+// ossim_uint32 lengthY = outH - padding()*2; // now setup the bilinear interpolation length for y direction
+ ossim_uint32 lengthX = outW;// - padding(); // now setup the bilinear interpolation length for x direction
+ ossim_uint32 lengthY = outH;// - padding(); // now setup the bilinear interpolation length for y direction
+ result->allocateImage(outW, outH, 1, getPixelFormat(), getDataType(), getPacking());
+
+ T* destData = (T*)result->data();
+ T* srcData = (T*)data();
+
+ ossim_uint32 xidx = 0;
+ ossim_uint32 yidx = 0;
+
+ ossim_uint32 inputOffsetY = 0;
+ ossim_uint32 inputOffset = 0;
+ ossim_uint8 testLocation = 0;
+ ossim_uint32 destOffset = outOriginY*outW + outOriginX;
+ // first resample the interior points that aren't padding points
+ //
+ for(yidx = 0; yidx < lengthY; ++yidx)
+ {
+ inputOffsetY = ((yidx>>1)+inOriginY)*srcW; // offset for padding along y
+ for(xidx = 0; xidx < lengthX; ++xidx)
+ {
+ inputOffset = inputOffsetY + ((xidx>>1)+inOriginX);
+ testLocation = ((yidx&1) << 1) | (xidx&1); // test even odd resampling
+ switch(testLocation)
+ {
+ case 0: // if none are odd then just copy the point over
+ {
+ destData[destOffset+xidx] = srcData[inputOffset];
+ break;
+ }
+ case 1: // if x is odd the do horizontal edge post
+ {
+ destData[destOffset+xidx] = (srcData[inputOffset] +
+ srcData[inputOffset+1])*.5;
+ break;
+ }
+ case 2: // if y is odd then do vertical edge post
+ {
+ destData[destOffset+xidx] = (srcData[inputOffset] +
+ srcData[inputOffset+srcW])*.5;
+ break;
+ }
+ case 3: // do center post if both bits are set
+ {
+ destData[destOffset+xidx] = (srcData[inputOffset] +
+ srcData[inputOffset+srcW]+
+ srcData[inputOffset+srcW+1]+
+ srcData[inputOffset+1]
+ )*.25;
+ break;
+ }
+ default:
+ {
+ destData[destOffset+xidx] = srcData[inputOffset];
+ }
+ }
+ }
+ destOffset += outW;
+ }
+
+ result->setMinMax(minValue(), maxValue());
+
+#if 0
+ // now scale the edges
+ //
+ destData = (T*)result->data();
+ srcData = (T*)data();
+ T* rightDestData = (T*)result->data() + outW-1;
+ T* rightSrcData = (T*)data() + srcW - 1;
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < outH; ++idx)
+ {
+ inputOffset = (idx>>1)*srcW;
+ testLocation = (idx&1); // test even odd resampling
+ destOffset = idx*outW;
+ switch(testLocation)
+ {
+ case 0: // if none are odd then just copy the point over
+ {
+ destData[destOffset] = srcData[inputOffset];
+ rightDestData[destOffset] = rightSrcData[inputOffset];
+ break;
+ }
+ case 1: // if x is odd the do vertical edge post
+ {
+ destData[destOffset] = (srcData[inputOffset] +
+ srcData[inputOffset+srcW] )*.5;
+ rightDestData[destOffset] = (rightSrcData[inputOffset] +
+ rightSrcData[inputOffset + srcW])*.5;
+ break;
+ }
+ }
+ }
+ destData = (T*)result->data();
+ srcData = (T*)data();
+ T* destDataTop = (T*)result->data() + (outH-1)*outW;
+ T* srcDataTop = (T*)data() + (srcH-1)*srcW;
+ for(idx = 0; idx < outW; ++idx)
+ {
+ inputOffset = (idx>>1);
+ testLocation = (idx&1); // test even odd resampling
+ switch(testLocation)
+ {
+ case 0: // if none are odd then just copy the point over
+ {
+ destData[idx] = srcData[inputOffset];
+ destDataTop[idx] = srcDataTop[inputOffset];
+ break;
+ }
+ case 1: // if x is odd the do horizontal edge post
+ {
+ destData[idx] = (srcData[inputOffset] +
+ srcData[inputOffset+1])*.5;
+ destDataTop[idx] = (srcDataTop[inputOffset] +
+ srcDataTop[inputOffset + 1])*.5;
+ break;
+ }
+ }
+ }
+#endif
+ return result;
+}
+
+template<class T>
+void ossimPlanetImage::copySubImageAndInsertPointsPowerOf2(T dummy,
+ int x, // starting x
+ int y, // starting y
+ ossim_uint32 lengthx, // length x
+ ossim_uint32 lengthy, // length y
+ ossimPlanetImage* source)
+{
+ ossim_uint32 srcWidth = source->s();
+ ossim_uint32 myWidth = s();
+ T* myData = (T*)data();
+ T* srcData = (T*)source->data();
+
+ ossim_float64 minValue = 1.0/FLT_EPSILON;
+ ossim_float64 maxValue = -minValue;
+// GLint internalFormat = getInternalTextureFormat();
+
+ srcData = srcData + y*srcWidth + x;
+
+ //std::cout << "SRC W = " << source->s() << std::endl
+ //<< "SRC H = " << source->t() << std::endl;
+ //std::cout << "DEST W = " << s() << std::endl
+ //<< "DEST H = " << t() << std::endl;
+ // copy the shared points then go back through and fill in
+ // the holes with a bilinear estimate
+ //
+ ossim_uint32 idxY = 0;
+ ossim_uint32 idxX = 0;
+ ossim_uint32 myHeight = t();
+ ossim_uint32 inputOffsetY = 0;
+ ossim_uint32 inputOffset = 0;
+ ossim_uint8 testLocation=0;
+ for(idxY = 0; idxY < myHeight; ++idxY)
+ {
+ inputOffsetY = (idxY>>1)*srcWidth;
+ for(idxX = 0; idxX < myWidth; ++idxX)
+ {
+ inputOffset = inputOffsetY + (idxX>>1);
+ testLocation = ((idxY&1) << 1) | (idxX&1);
+ switch(testLocation)
+ {
+ case 0: // if none are odd then just copy the point over
+ {
+ *myData = srcData[inputOffset];
+ break;
+ }
+ case 1: // if x is odd the do horizontal edge post
+ {
+ *myData = (srcData[inputOffset] +
+ srcData[inputOffset+1])*.5;
+ break;
+ }
+ case 2: // if y is odd then do vertical edge post
+ {
+ *myData = (srcData[inputOffset] +
+ srcData[inputOffset+srcWidth])*.5;
+ break;
+ }
+ case 3: // do center post if both bits are set
+ {
+ *myData = (srcData[inputOffset] +
+ srcData[inputOffset+srcWidth]+
+ srcData[inputOffset+srcWidth+1]+
+ srcData[inputOffset+1]
+ )*.25;
+ break;
+ }
+ default:
+ {
+ *myData = srcData[inputOffset];
+ }
+
+
+ }
+ if(*myData > maxValue) maxValue = *myData;
+ if(*myData < minValue) minValue = *myData;
+
+ ++myData;
+ }
+ }
+
+ theMinValue.resize(1);
+ theMaxValue.resize(1);
+ theMinValue[0] = minValue;
+ theMaxValue[0] = maxValue;
+}
+
+osg::Vec2 ossimPlanetImage::deltas(ossim_int32 x,
+ ossim_int32 y)const
+{
+ osg::Vec2 delta(0.0,0.0);
+ GLint internalFormat = getInternalTextureFormat();
+
+ // we only support single band float for delta lookups
+ if(internalFormat != GL_LUMINANCE) return delta;
+ if(getDataType()!=GL_FLOAT)
+ {
+ return delta;
+ }
+
+ if (x==0)
+ {
+ delta.x() = (elevationValue(x+1,y)-elevationValue(x,y));
+ }
+ else if (x==getWidth()-1)
+ {
+ delta.x() = (elevationValue(x,y)-elevationValue(x-1,y));
+ }
+ else // assume 0<c<_numColumns-1
+ {
+ delta.x() = 0.5f*(elevationValue(x+1,y)-elevationValue(x-1,y));
+ }
+
+ if (y==0)
+ {
+ delta.y() = (elevationValue(x,y+1)-elevationValue(x,y));
+ }
+ else if (y==getHeight()-1)
+ {
+ delta.y() = (elevationValue(x,y)-elevationValue(x,y-1));
+ }
+ else // assume 0<r<_numRows-1
+ {
+ delta.y() = 0.5f*(elevationValue(x,y+1)-elevationValue(x,y-1));
+ }
+
+ return delta;
+}
+
+ossim_uint64 ossimPlanetImage::sizeInBytes()const
+{
+ return ((((ossim_uint64)getRowSizeInBytes())*((ossim_uint64)_t)*((ossim_uint64)_r))+
+ (ossim_uint64)sizeof(ossimPlanetImage));
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetInteractionController.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetInteractionController.cpp
new file mode 100644
index 0000000..9f02b9e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetInteractionController.cpp
@@ -0,0 +1,338 @@
+#include <algorithm>
+#include <fstream>
+
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+#include <ossimPlanet/ossimPlanetInteractionController.h>
+#include <ossim/base/ossimCommon.h>
+
+ossimPlanetInteractionController* ossimPlanetInteractionController::instance_ = NULL;
+
+ossimPlanetInteractionController::ossimPlanetInteractionController()
+{
+ setPathnameAndRegister(":iac");
+}
+
+ossimPlanetInteractionController::~ossimPlanetInteractionController()
+{
+ ossimPlanetActionRouter::instance()->unregisterReceiver(this);
+ deviceList_.clear();
+}
+
+void ossimPlanetInteractionController::registerDevice(ossimPlanetInputDevice* d)
+{
+ // assert(d != NULL);
+
+ if(!d) return;
+
+ deviceList_.push_back(d);
+}
+
+void ossimPlanetInteractionController::unregisterDevice(ossimPlanetInputDevice* d)
+{
+ // assert(d != NULL);
+ if(!d) return;
+ DeviceList::iterator i = find(deviceList_.begin(), deviceList_.end(), d);
+ if (i != deviceList_.end())
+ deviceList_.erase(i);
+}
+
+void ossimPlanetInteractionController::processPendingInputs()
+{
+ for (int i = 0; i < (int)deviceList_.size(); i++)
+ deviceList_[i]->processInput();
+}
+
+void ossimPlanetInteractionController::defineInteractionValuator(const std::string& name, double minValue, double maxValue)
+{
+ if(name.empty() || ossim::isnan(minValue) || ossim::isnan(maxValue)) return;
+ // assert(!name.empty());
+ // assert(!ossim::isnan(minValue));
+ // assert(!ossim::isnan(maxValue));
+
+ valuators_[name] = ossimPlanetInteractionValuatorData(minValue, maxValue);
+
+ // assert(!ossim::isnan(interactionValuatorValue(name)));
+}
+
+float ossimPlanetInteractionController::interactionValuatorValue(const std::string& interactionValuator) const
+{
+ float result = ossim::nan();
+
+ std::map<std::string, ossimPlanetInteractionValuatorData>::const_iterator i = valuators_.find(interactionValuator);
+ if (i != valuators_.end())
+ result = i->second.value;
+ else
+ std::cerr << "ossimPlanetInteractionController::interactionValuatorValue(): no defined interactionValuator " << interactionValuator << std::endl;
+ return result;
+}
+
+void ossimPlanetInteractionController::bind(const std::string& event, const ossimPlanetAction& a)
+{
+ if(event.empty()) return;
+ // assert(!event.empty());
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theBoundActionsMutex);
+ boundActions_[event] = a.clone();
+}
+
+void ossimPlanetInteractionController::unbind(const std::string& event)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theBoundActionsMutex);
+ std::map<std::string, osg::ref_ptr<ossimPlanetAction> >::iterator i = boundActions_.find(event);
+
+ if (i != boundActions_.end())
+ {
+ boundActions_.erase(i);
+ }
+}
+
+void ossimPlanetInteractionController::unbindAll()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theBoundActionsMutex);
+ boundActions_.clear();
+}
+
+void ossimPlanetInteractionController::tie(const std::string& valuatorList)
+{
+ std::vector<std::string> list;
+ bool unbalanced;
+ mkUtils::lexBraceQuotedTokens(valuatorList, 0, " \t", &list, &unbalanced);
+
+ if (!unbalanced && list.size() > 1) {
+ std::vector<std::string>& v = deviceTies_[list[0]]; // deviceTies_[] creates a blank entry if needed
+ v.clear();
+ for (unsigned int i = 1; i < list.size(); i++)
+ if (!ossim::isnan(interactionValuatorValue(list[i])))
+ v.push_back(list[i]);
+ } else
+ std::cerr << "ossimPlanetInteractionController::tie() had malformed interactionValuatorList, ignoring: " << valuatorList << std::endl;
+}
+
+void ossimPlanetInteractionController::untie(const std::string& deviceValuator)
+{
+ std::map<std::string, std::vector<std::string> >::iterator i = deviceTies_.find(deviceValuator);
+ if (i != deviceTies_.end())
+ deviceTies_.erase(i);
+}
+
+void ossimPlanetInteractionController::untieAll()
+{
+ deviceTies_.clear();
+}
+
+void ossimPlanetInteractionController::writeConfiguration(std::ostream& stream) const
+{
+ for (std::map<std::string, std::vector<std::string> >::const_iterator i = deviceTies_.begin(); i != deviceTies_.end(); i++) {
+ stream << ":iac tie " << i->first;
+ const std::vector<std::string>& v = i->second;
+ for (unsigned int j = 0; j < v.size(); j++)
+ stream << ' ' << v[j];
+ stream << std::endl;
+ }
+
+ for (std::map<std::string, osg::ref_ptr<ossimPlanetAction> >::const_iterator i = boundActions_.begin(); i != boundActions_.end(); i++)
+ stream << ":iac bind " << i->first << " {" << *i->second << '}' << std::endl;
+}
+
+void ossimPlanetInteractionController::executeBoundAction(const std::string& event)
+{
+ // Debug::log("InteractionController_events") << "--- " << event << std::endl;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theBoundActionsMutex);
+
+ std::map<std::string,osg::ref_ptr< ossimPlanetAction> >::const_iterator i = boundActions_.find(event);
+ if (i != boundActions_.end())
+ i->second->execute();
+}
+
+void ossimPlanetInteractionController::updateInteractionValuators(const std::string& deviceValuator, float normalizedValue)
+{
+ // XXX assert(mkUtils::inInterval(normalizedValue, 0.0f, 1.0f));
+
+ // Debug::log("InteractionController_events") << "--- " << deviceValuator << " = " << normalizedValue << std::endl;
+
+ std::map<std::string, std::vector<std::string> >::iterator i = deviceTies_.find(deviceValuator);
+ if (i != deviceTies_.end())
+ {
+ std::vector<std::string>& v = i->second;
+ for (unsigned int j = 0; j < v.size(); j++)
+ {
+ std::map<std::string, ossimPlanetInteractionValuatorData>::iterator iter = valuators_.find(v[j]);
+ if (iter != valuators_.end())
+ {
+ // ossimPlanetInteractionValuatorData data& = (valuators_.find(v[j])->second);
+ iter->second.value = normalizedValue*iter->second.maxMinusMin + iter->second.min;
+ }
+ }
+ }
+}
+
+void ossimPlanetInteractionController::execute(const ossimPlanetAction& action)
+{
+ const ossimPlanetDestinationCommandAction* a = action.toDestinationCommandAction();
+ const ossimPlanetXmlAction* xml = action.toXmlAction();
+ if(a)
+ {
+ destinationCommandExecute(*a);
+ }
+ else if(xml)
+ {
+ xmlExecute(*xml);
+ }
+
+}
+
+void ossimPlanetInteractionController::xmlExecute(const ossimPlanetXmlAction& a)
+{
+ ossimString command = a.command();
+ if(command == "Bind")
+ {
+ ossimString bindString;
+ ossimPlanetXmlAction tempAction;
+ // need to create objects for these so we can do a common string encode. We will do it here
+ // for now and move out later for common use.
+ //
+ ossim_uint32 idx;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ for(idx = 0; idx < children.size();++idx)
+ {
+ if(children[idx]->getTag() == "Keyboard")
+ {
+ ossimString key = children[idx]->getAttributeValue("key");
+ ossimString metaKey = children[idx]->getAttributeValue("metaKey");
+ if(key == " ")
+ {
+ key = "space";
+ }
+ bindString = key;
+ if(!metaKey.empty())
+ {
+ bindString = metaKey + "_" + bindString;
+ }
+ bindString += "_key";
+ }
+ else if(children[idx]->getTag() == "Mouse")
+ {
+
+ }
+ else if(children[idx]->findAttribute("target").valid())
+ {
+ tempAction.setXmlNode((ossimXmlNode*)children[idx]->dup());
+ }
+
+ if(tempAction.xmlNode().valid())
+ {
+ bind(bindString, tempAction);
+ }
+ }
+ }
+ else if(command == "Unbind")
+ {
+
+ }
+ else if(command == "UnbindAll")
+ {
+ unbindAll();
+ }
+}
+
+void ossimPlanetInteractionController::destinationCommandExecute(const ossimPlanetDestinationCommandAction& a)
+{
+
+ ossimString command = a.command();
+ if (command == "bind")
+ {
+ if (a.argCount() == 2)
+ {
+ if (!a.arg(1).empty())
+ bind(a.arg(1),
+ ossimPlanetDestinationCommandAction(a.arg(2)));
+ else
+ a.printError("cannot bind empty event name because this name is guaranteed a noop");
+ } else
+ a.printError("bad argument count");
+
+ }
+ else if (command == "unbind")
+ {
+ for (unsigned int i = 1; i <= a.argCount(); i++)
+ unbind(a.arg(i));
+
+ }
+ else if (command == "unbindall")
+ {
+ unbindAll();
+
+ }
+ else if (command == "tie")
+ {
+ if (a.argCount() > 1)
+ tie(a.argListSource());
+ else
+ a.printError("bad argument count: need device valuator followed by 1 or more interaction valuator");
+
+ }
+ else if (command == "untie")
+ {
+ for (unsigned int i = 1; i <= a.argCount(); i++)
+ untie(a.arg(i));
+
+ }
+ else if (command == "untieall")
+ {
+ untieAll();
+
+ }
+ else if (command == "printvaluators")
+ {
+ std::map<std::string, ossimPlanetInteractionValuatorData>::const_iterator i;
+ for (i = valuators_.begin(); i != valuators_.end(); i++)
+ std::cout << i->first << " = " << i->second.value << "\trange [" << i->second.min << ',' << (i->second.maxMinusMin + i->second.min) << ']' << std::endl;
+
+ }
+ else if (command == "writeconfiguration")
+ {
+ if (a.argCount() == 0)
+ {
+ writeConfiguration(std::cout);
+ }
+ else if (a.argCount() == 1)
+ {
+ std::ofstream f(a.arg(1).c_str());
+ if (!f)
+ std::cerr << "cannot open file " << a.arg(1) << " for :iac writeconfiguration" << std::endl;
+ else
+ writeConfiguration(f);
+ }
+ else
+ a.printError("bad argument count, must specify a filename, or no argument for stdout");
+
+ }
+ else if (command == "doevents")
+ {
+ for (unsigned int i = 1; i <= a.argCount(); i++)
+ executeBoundAction(a.arg(i));
+
+ }
+ else if (command == "updatevaluators")
+ {
+ if (a.argCount() % 2 == 0) {
+ for (unsigned int i = 1; i < a.argCount(); i += 2) {
+ float x = mkUtils::asFloat(a.arg(i+1));
+ if (mkUtils::inInterval(x, 0.0f, 1.0f)) {
+ std::map<std::string, ossimPlanetInteractionValuatorData>::iterator iter = valuators_.find(a.arg(i));
+ if (iter != valuators_.end())
+ {
+ iter->second.value = x*iter->second.maxMinusMin + iter->second.min;
+ }
+ else
+ a.printError("Undefined simulation variable " + a.arg(i));
+ }
+ }
+ } else
+ a.printError("bad arg count");
+
+ } else {
+ a.printError("ossimPlanetInteractionController Action not understood");
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetIoRoutableMessageHandler.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetIoRoutableMessageHandler.cpp
new file mode 100644
index 0000000..4a7113d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetIoRoutableMessageHandler.cpp
@@ -0,0 +1,20 @@
+#include <ossimPlanet/ossimPlanetIoRoutableMessageHandler.h>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+
+bool ossimPlanetIoRoutableMessageHandler::handleMessage(osg::ref_ptr<ossimPlanetMessage> message)
+{
+ bool result = false;
+ if(!enableFlag()) return result;
+ if(!message->data().empty())
+ {
+ if(*(message->data().begin()) == ':')
+ {
+ result = true;
+ ossimPlanetDestinationCommandAction(std::string(message->data().begin(),
+ message->data().end())).execute();
+ }
+ }
+
+ return result;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetIoSocket.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetIoSocket.cpp
new file mode 100644
index 0000000..301e73e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetIoSocket.cpp
@@ -0,0 +1,665 @@
+#include <ossimPlanet/ossimPlanetIoSocket.h>
+#include <iostream>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <sstream>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotify.h>
+#include <algorithm>
+
+static ossimTrace traceDebug("ossimPlanetIoSocket:debug");
+
+ossimPlanetIoSocket::ossimPlanetIoSocket()
+ :ossimPlanetIo(),
+ theSocket(new netSocket()),
+ theHost(""),
+ thePort(0),
+ theIoType(""),
+ theStreamingFlag(false),
+ theTempBuffer(4096),
+ //theAutoCloseOnPeerShutdownFlag(true),
+ theAutoReconnectFlag(true),
+ theAutoReconnectInterval(5000),
+ theMaxBytesToSendPerIo(1024*4),
+ theMaxOutgoingBacklogInBytes(1024*1024),
+ theTotalBytesToSend(0),
+ theFirstReadFlag(true)
+{
+ setIoDirection(ossimPlanetIoDirection_INOUT);
+}
+
+ossimPlanetIoSocket::~ossimPlanetIoSocket()
+{
+ if(theSocket)
+ {
+ closeIo();
+ delete theSocket;
+ theSocket = 0;
+ }
+}
+
+void ossimPlanetIoSocket::setHandle(int handle)
+{
+ theSocket->setHandle(handle);
+}
+
+void ossimPlanetIoSocket::searchName(ossimString& searchNameResult)const
+{
+ if(name().empty())
+ {
+ searchNameResult = host() + ":" + ossimString::toString(thePort);
+ }
+ else
+ {
+ searchNameResult = name() + ":" + ossimString::toString(thePort);
+ }
+}
+
+ossim_uint32 ossimPlanetIoSocket::read(char* buffer, ossim_uint32 bufferSize, ossimPlanetIo::IoResultType& ioResult)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoMutex);
+ ossim_uint32 resultBytesRead = 0;
+ if(handle() < 0)
+ {
+ ioResult = IO_FAIL;
+ return resultBytesRead;
+ }
+
+// bool useRecvFlag = (theStreamingFlag||(theHost.empty()||(thePort <=0)));
+ int bytes = -1;
+// if(useRecvFlag)
+ {
+ bytes = theSocket->recv(buffer, bufferSize);
+ }
+// else
+// {
+// netAddress add(theHost, thePort);
+// bytes = theSocket->recvfrom(buffer, bufferSize, 0, &add);
+// }
+ if(bytes>0)
+ {
+ resultBytesRead = bytes;
+ ioResult = IO_SUCCESS;
+ }
+ else if(bytes < 0) // peer performed shutdown
+ {
+ if(!theSocket->isNonBlockingError())
+ {
+ ioResult = IO_FAIL;
+ }
+ else
+ {
+ ioResult = IO_NO_DATA;
+ }
+ }
+ else
+ {
+ ioResult = IO_FAIL;
+ }
+
+ return resultBytesRead;
+}
+
+
+ossim_uint32 ossimPlanetIoSocket::write(const char* buffer, ossim_uint32 bufferSize, ossimPlanetIo::IoResultType& ioResult)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoMutex);
+ ossim_uint32 resultBytesWritten = 0;
+ if(handle() < 0)
+ {
+ ioResult = IO_NO_DATA;
+ return resultBytesWritten;
+ }
+// bool useSendFlag = (theStreamingFlag||theHost.empty()||(thePort <=0));
+ int bytes = -1;
+
+// if(useSendFlag)
+ {
+ bytes = theSocket->send(buffer, bufferSize);
+ }
+// else
+// {
+// netAddress add(theHost, thePort);
+// bytes = theSocket->sendto(buffer, bufferSize, 0, &add);
+// }
+ if(bytes > 0)
+ {
+ resultBytesWritten = bytes;
+ ioResult = IO_SUCCESS;
+ }
+ else if(bytes == 0)
+ {
+ ioResult = IO_NO_DATA;
+ }
+ else
+ {
+ if(!theSocket->isNonBlockingError())
+ {
+ ioResult = IO_FAIL;
+ }
+ else
+ {
+ ioResult = IO_NO_DATA;
+ }
+ }
+
+ return resultBytesWritten;
+}
+
+
+bool ossimPlanetIoSocket::setSocket(const ossimString& host,
+ int port,
+ const ossimString& ioType)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theSocketMutex);
+ return protectedSetSocket(host, port, ioType);
+}
+
+bool ossimPlanetIoSocket::protectedSetSocket(const ossimString& host,
+ int port,
+ const ossimString& ioType)
+{
+ bool result = false;
+ closeIo();
+ setFinishedFlag(false);
+
+ theHost = host;
+ theIoType = ioType;
+ thePort = port;
+ theStreamingFlag = theIoType == "tcp";
+ //std::cout << "Trying " << host << " " << port << " " << ioType << std::endl;
+ // if I am enabled or not enabled and can't do a reconect in the io thread then
+ // go ahead and do a connection now
+ //
+ if((enableFlag())||
+ (!enableFlag()&&!theAutoReconnectFlag))
+ {
+ if (makeClientSocket())
+ {
+ pushConnectionHeader();// add connection header if one exists
+ result = true;
+ }
+ }
+
+ nonblock();
+
+ theFirstReadFlag = true;
+ return result;
+}
+
+bool ossimPlanetIoSocket::nonblock()
+{
+ return setBlockingFlag(false);
+}
+
+bool ossimPlanetIoSocket::setBlockingFlag(bool flag)
+{
+ if (theSocket->getHandle() < 0)
+ {
+ return false;
+ }
+ theSocket->setBlocking( false );
+
+ return true;
+}
+
+void ossimPlanetIoSocket::setEnableFlag(bool flag)
+{
+ bool stateChanged = false;
+ // if we are currently going from enabled to disabled then clear the lists after we disable
+ // ourselves
+ if(!flag&&enableFlag())
+ {
+ stateChanged = true;
+ }
+ ossimPlanetIo::setEnableFlag(flag);
+ if(stateChanged)
+ {
+ clearAllBuffers();
+ }
+
+}
+
+const ossimString& ossimPlanetIoSocket::host()const
+{
+ return theHost;
+}
+
+int ossimPlanetIoSocket::port()const
+{
+ return thePort;
+}
+
+const ossimString& ossimPlanetIoSocket::ioType()const
+{
+ return theIoType;
+}
+
+void ossimPlanetIoSocket::performIo()
+{
+ ossimPlanetIo::IoResultType ioResult;
+ bool hasOutput = false;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theSocketMutex);
+
+ if(theSocket->getHandle()<0)
+ {
+ if(theAutoReconnectFlag&&enableFlag())
+ {
+ if(theLastTick == 0)
+ {
+ theLastTick = osg::Timer::instance()->tick();
+ }
+ else if(osg::Timer::instance()->delta_m(theLastTick, osg::Timer::instance()->tick()) > theAutoReconnectInterval)
+ {
+ theLastTick = 0; // reset the next try
+ protectedSetSocket(theHost, thePort, theIoType); // connect and see if we can perform io on next cycle
+ if(theSocket->getHandle() >=0)
+ {
+ pushConnectionHeader();
+ }
+ }
+ return;
+ }
+ else if(!theAutoReconnectFlag)
+ {
+ setFinishedFlag(true);
+ return;
+ }
+ else
+ {
+ return;
+ }
+ }
+ if(ioDirection()&ossimPlanetIoDirection_OUT&&enableFlag())
+ {
+ addToOutputBufferIfNeeded();
+ OpenThreads::ScopedLock<OpenThreads::Mutex> outBufferLock(theOutBufferMutex);
+ if(theOutBuffer.size())
+ {
+ hasOutput = true;
+ // do any sends if we are an output socket
+ ossim_uint32 bytesToSend = ossim::min((ossim_uint32)theOutBuffer.size(),
+ (ossim_uint32)maxBytesToSendPerIo());
+
+ ossim_uint32 bytes = write((char*)(&theOutBuffer.front()), bytesToSend, ioResult);
+ if(ioResult == IO_SUCCESS)
+ {
+ theOutBuffer.erase(theOutBuffer.begin(),
+ theOutBuffer.begin() + bytes);
+
+ // theTotalBytesToSend-=bytes;
+// if(theTotalBytesToSend < 0)
+// {
+// theTotalBytesToSend = 0;
+// }
+ }
+// if(theOutBuffer.empty())
+// {
+// theTotalBytesToSend = 0;
+// }
+ }
+ }
+ else
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> outBufferLock(theOutBufferMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> outQueueLock(theOutQueueMutex);
+ theOutBuffer.clear();
+ theOutQueue.clear();
+ }
+ if(ioDirection()&ossimPlanetIoDirection_IN)
+ {
+ // do any receives if we are an input socket
+ ossim_uint32 bytes = read(&theTempBuffer.front(), theTempBuffer.size(), ioResult);
+ if(ioResult==IO_SUCCESS)
+ {
+ theFirstReadFlag = false; // we have performed the first read so set the flag now to false
+ if(enableFlag())
+ {
+ //std::cout << ossimString(theTempBuffer.begin(), theTempBuffer.begin()+bytes) << "\n";
+ theInBuffer.insert(theInBuffer.end(), theTempBuffer.begin(), theTempBuffer.begin()+bytes);
+ }
+ }
+ else if(ioResult == IO_FAIL) // peer performed shutdown
+ {
+ if(traceDebug())
+ {
+ ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPlanetIoSocket::performIo(): read io failed" << std::endl;
+ }
+ //if(!theFirstReadFlag)
+ closeIo();
+ if(!theAutoReconnectFlag)
+ {
+ setFinishedFlag(true);
+ }
+ }
+ bool doneSending = false;
+ while(!theInBuffer.empty()&&!doneSending)
+ {
+ // check if start of old style router or
+ // new style XML token
+ //
+// bool hasValidStartToken = ((theInBuffer[(size_t)0] == ':')||
+// (theInBuffer[(size_t)0] == '<');
+ bool hasValidStartToken = (theInBuffer[(size_t)0] == '<');
+ if(!hasValidStartToken)
+ {
+ // then skip til we find the first valid token
+ //
+ const char tokens[]={'<'};
+ ossimPlanetIo::ByteBufferType::iterator iter = std::find_first_of(theInBuffer.begin(),
+ theInBuffer.end(),
+ tokens,
+ tokens+1);
+ if(iter == theInBuffer.end())
+ {
+ theInBuffer.clear();
+ }
+ else
+ {
+ // remove the characters since not a valid start token
+ //
+ theInBuffer.erase(theInBuffer.begin(),
+ iter);
+ }
+ }
+
+ if(!theInBuffer.empty())
+ {
+ {
+ ossimString value;
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ std::istringstream in(ossimString(theInBuffer.begin(),
+ theInBuffer.end()));
+ if(node->read(in))
+ {
+ //std::cout<<(*node) << "\n";
+ if(node->getTag() == "Message")
+ {
+ // container for multiple Actions
+ //
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = node->getChildNodes();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < childNodes.size();++idx)
+ {
+ if(childNodes[idx]->getAttributeValue(value, "target"))
+ {
+ ossimPlanetXmlAction action;
+ action.setXmlNode(childNodes[idx]);
+ action.execute();
+ }
+ }
+ }
+ else if(node->getAttributeValue(value, "target")) // is it a direct message
+ {
+ if(traceDebug())
+ {
+ ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPlanetIoSocket::performIo(): processing message = " << ossimString(theInBuffer.begin(),
+ theInBuffer.begin()+in.tellg())<<std::endl;
+ }
+ // must be a direct action object
+ //
+ ossimPlanetXmlAction action;
+ action.setXmlNode(node);
+ action.execute();
+ }
+ else // will have to do a custom parse later.
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theInQueueMutex);
+
+ theInQueue.push(new ossimPlanetMessage("",std::vector<char>(theInBuffer.begin(),
+ theInBuffer.begin()+in.tellg())));
+ }
+ theInBuffer.erase(theInBuffer.begin(),
+ theInBuffer.begin()+in.tellg());
+ }
+ else
+ {
+ if(traceDebug())
+ {
+ ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPlanetIoSocket::performIo(): Read had a parse error that stopped short of the end of buffer location" << std::endl;
+ }
+ //if(!theFirstReadFlag)
+ // if stopped short then we had a parse error. Just erase the buffer up to the error and keep trying
+ // if we reached the end the we may need more
+ //
+ if(((ossim_int64)in.tellg() >=0) && ((ossim_int64)in.tellg() < (ossim_int64)theInBuffer.size()))
+ {
+// std::cout << "ERROR=======> " << ossimString(theInBuffer.begin(),
+// theInBuffer.begin()+in.tellg()) << "\n";
+ theInBuffer.erase(theInBuffer.begin(),
+ theInBuffer.begin()+in.tellg());
+
+ }
+ doneSending = true;
+ }
+ }
+ }
+ }
+ }
+ else // only outgoing so let's do a check to see if the peer shutdown
+ {
+ theInBuffer.clear();
+ // let's ignor any incoming bytes and do a check to see if we are still connected to the peer
+
+ read(&theTempBuffer.front(), theTempBuffer.size(), ioResult);
+ if(ioResult == IO_FAIL) // peer performed shutdown
+ {
+ closeIo();
+ theOutBuffer.clear();
+// theTotalBytesToSend=0;
+
+ if(!theAutoReconnectFlag)
+ {
+ setFinishedFlag(true);
+ }
+ }
+ }
+ if(finishedFlag())
+ {
+ theInBuffer.clear();
+ theOutBuffer.clear();
+ }
+}
+
+bool ossimPlanetIoSocket::pushMessage(osg::ref_ptr<ossimPlanetMessage> message, bool forcePushFlag)
+{
+ if(!(ioDirection()&ossimPlanetIoDirection_OUT) || !enableFlag()) return false;
+ bool result = true;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOutQueueMutex);
+ OutQueueType::iterator iter = theOutQueue.begin();
+ if(!message->id().empty())
+ {
+ while(iter != theOutQueue.end())
+ {
+ if((*iter)->id() == message->id())
+ {
+ OutQueueType::iterator iter2 = theOutQueue.erase(iter);
+ theOutQueue.insert(iter2, message);
+ std::cout << "REPLACING!!!!!" << std::endl;
+ return result;
+ }
+ ++iter;
+ }
+ }
+ theOutQueue.push_back(message);
+
+ return result;
+#if 0
+ bool needTerminator = message[(size_t)0] == ':'; // check for old : action message format
+ if(!enableFlag()) return false;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOutGoingMutex);
+ if(forcePushFlag) // we will always support one message no matter the size
+ {
+ theOutBuffer.push_back(message);
+ if(needTerminator)
+ {
+ theOutBuffer.back().push_back(terminator());
+ }
+ theTotalBytesToSend += theOutBuffer.back().size();
+ }
+ else if(theTotalBytesToSend > (int)theMaxOutgoingBacklogInBytes)
+ {
+ // create some kind of notification for this
+ result = false;
+ }
+ else
+ {
+ if(theSocket->getHandle() < 0) return false;
+ theOutBuffer.push_back(message);
+ theOutBuffer.back().push_back(terminator());
+ if(needTerminator)
+ {
+ theOutBuffer.back().push_back(terminator());
+ }
+ theTotalBytesToSend += theOutBuffer.back().size();
+ }
+ return result;
+#endif
+}
+
+osg::ref_ptr<ossimPlanetMessage> ossimPlanetIoSocket::popMessage()
+{
+ if(!enableFlag()) return 0;
+ theInQueueMutex.lock();
+ osg::ref_ptr<ossimPlanetMessage> message;
+ if(!theInQueue.empty())
+ {
+ message = theInQueue.front();
+ theInQueue.pop();
+ }
+ theInQueueMutex.unlock();
+
+ return message;
+}
+
+void ossimPlanetIoSocket::clearAllBuffers()
+{
+ theInQueueMutex.lock();
+ while(!theInQueue.empty())theInQueue.pop();
+ theInQueueMutex.unlock();
+ theInBuffer.clear();
+ theOutBufferMutex.lock();
+ theOutBuffer.clear();
+// theTotalBytesToSend = 0;
+ theOutBufferMutex.unlock();
+ theOutQueueMutex.lock();
+ theOutQueue.clear();
+ theOutQueueMutex.unlock();
+}
+
+//void ossimPlanetIoSocket::setAutoCloseOnPeerShutdownFlag(bool flag)
+//{
+// theAutoCloseOnPeerShutdownFlag = flag;
+//}
+
+//bool ossimPlanetIoSocket::autoCloseOnPeerShutdownFlag()const
+//{
+// return theAutoCloseOnPeerShutdownFlag;
+//}
+
+void ossimPlanetIoSocket::setAutoReconnectFlag(bool flag)
+{
+ theAutoReconnectFlag = flag;
+}
+
+bool ossimPlanetIoSocket::autoReconnectFlag()const
+{
+ return theAutoReconnectFlag;
+}
+
+void ossimPlanetIoSocket::setAutoReconnectInterval(ossim_uint32 milliseconds)
+{
+ theAutoReconnectInterval = milliseconds;
+}
+
+ossim_uint32 ossimPlanetIoSocket::autoReconnectInterval()const
+{
+ return theAutoReconnectInterval;
+}
+
+void ossimPlanetIoSocket::setMaxOutputBacklogInBytes(ossim_uint32 bytes)
+{
+ theMaxOutgoingBacklogInBytes = bytes;
+}
+
+ossim_uint32 ossimPlanetIoSocket::maxOutputBacklogInBytes()const
+{
+ return theMaxOutgoingBacklogInBytes;
+}
+
+void ossimPlanetIoSocket::closeIo()
+{
+ theSocket->close();
+}
+
+bool ossimPlanetIoSocket::openIo()
+{
+ return setSocket(theHost, thePort, theIoType);
+}
+
+void ossimPlanetIoSocket::setMaxBytesToSendPerIo(ossim_uint32 byte)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMaxBytesToSendPerIoMutex);
+
+ theMaxBytesToSendPerIo = byte;
+}
+
+ossim_uint32 ossimPlanetIoSocket::maxBytesToSendPerIo()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMaxBytesToSendPerIoMutex);
+ return theMaxBytesToSendPerIo;
+}
+
+
+bool ossimPlanetIoSocket::makeClientSocket()
+{
+ if (!theSocket->open( theStreamingFlag ))
+ {
+ return false;
+ }
+
+ if(theStreamingFlag)
+ {
+ int testValue = theSocket->connect( theHost.c_str(), thePort );
+ if (testValue < 0)
+ {
+ theSocket->close();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetIoSocket::addToOutputBufferIfNeeded()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(theOutQueueMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(theOutBufferMutex);
+
+ if(theOutBuffer.empty()&&(!theOutQueue.empty()))
+ {
+ bool needTerminator = theOutQueue.front()->data()[(size_t)0] == ':'; // check for old : action message format
+ theOutBuffer.insert(theOutBuffer.end(), theOutQueue.front()->data().begin(), theOutQueue.front()->data().end());
+ if(needTerminator)
+ {
+ theOutBuffer.push_back(terminator());
+ }
+ theOutQueue.pop_front();
+ }
+#if 0
+ while((theOutBuffer.size() < maxBytesToSendPerIo())&&(!theOutQueue.empty()))
+ {
+ bool needTerminator = theOutQueue.front()->data()[(size_t)0] == ':'; // check for old : action message format
+ theOutBuffer.push_back(theOutQueue.front()->data());
+ if(needTerminator)
+ {
+ theOutBuffer.push_back(terminator());
+ }
+ // theTotalBytesToSend += theOutBuffer.size();
+ }
+#endif
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetIoSocketServerChannel.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetIoSocketServerChannel.cpp
new file mode 100644
index 0000000..f0b4943
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetIoSocketServerChannel.cpp
@@ -0,0 +1,330 @@
+#include <ossimPlanet/ossimPlanetIoSocketServerChannel.h>
+#include <ossimPlanet/ossimPlanetIoSocket.h>
+#include <iostream>
+ossimPlanetIoSocketServerChannel::ossimPlanetIoSocketServerChannel()
+ :ossimPlanetIo(),netChannel(),
+ theHost(""),
+ thePort(0),
+ theIoType("tcp"),
+ theIsTcp(true),
+ theAutoReconnectFlag(true),
+ theAutoReconnectInterval(10000),
+ theLastTick(0)
+{
+ setIoDirection(ossimPlanetIoDirection_IN);
+}
+
+ossimPlanetIoSocketServerChannel::~ossimPlanetIoSocketServerChannel()
+{
+ theIoListMutex.lock();
+ theIoList.clear();
+ theIoListMutex.unlock();
+ clearAllBuffers();
+ close();
+}
+
+void ossimPlanetIoSocketServerChannel::searchName(ossimString& searchNameResult)const
+{
+ if(name().empty())
+ {
+ searchNameResult = host() + ":" + ossimString::toString(thePort);
+ }
+ else
+ {
+ searchNameResult = name() + ":" + ossimString::toString(thePort);
+ }
+}
+
+bool ossimPlanetIoSocketServerChannel::setSocket(const std::string& host,
+ int port,
+ const std::string& ioType)
+{
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theSocketMutex);
+ return protectedSetSocket(host, port, ioType);
+}
+
+bool ossimPlanetIoSocketServerChannel::protectedSetSocket(const std::string& host,
+ int port,
+ const std::string& ioType)
+{
+
+ theIoList.clear();
+
+ theHost = host;
+ thePort = port;
+ theIoType = ioType;
+ theIsTcp = theIoType!="udp";
+ if(getHandle() > -1)
+ {
+ close();
+ }
+ if(open(theIsTcp))
+ {
+ if( bind("", port)<0)
+ {
+ close();
+ return false;
+ }
+// if(!theIsTcp)
+ {
+ setBlocking( false );
+ }
+// else
+ if(theIsTcp)
+ {
+ listen(32); // need to add something that is not hardcoded here
+ }
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+void ossimPlanetIoSocketServerChannel::setEnableFlag(bool flag)
+{
+ bool clearBuffersFlag = false;
+ // if we are currently going from enabled to disabled then clear the lists after we disable
+ // ourselves
+ if(!flag&&enableFlag())
+ {
+ clearBuffersFlag = true;
+ }
+ ossimPlanetIo::setEnableFlag(flag);
+}
+
+void ossimPlanetIoSocketServerChannel::clearAllBuffers()
+{
+ theInQueueMutex.lock();
+ while(!theInQueue.empty())theInQueue.pop();
+ theInQueueMutex.unlock();
+}
+
+const std::string& ossimPlanetIoSocketServerChannel::host()const
+{
+ return theHost;
+}
+
+const std::string& ossimPlanetIoSocketServerChannel::ioType()const
+{
+ return theIoType;
+}
+
+int ossimPlanetIoSocketServerChannel::port()const
+{
+ return thePort;
+}
+
+bool ossimPlanetIoSocketServerChannel::isTcp()const
+{
+ return theIsTcp;
+}
+
+void ossimPlanetIoSocketServerChannel::performIo()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theSocketMutex);
+ if(handle() < 0)
+ {
+ if(theAutoReconnectFlag)
+ {
+ if(theLastTick == 0)
+ {
+ theLastTick = osg::Timer::instance()->tick();
+ return;
+ }
+ else
+ {
+ double delta = osg::Timer::instance()->delta_m(theLastTick, osg::Timer::instance()->tick());
+
+ if(delta < 0.0)
+ {
+ theLastTick = 0;
+ }
+ else if(delta > theAutoReconnectInterval)
+ {
+ theLastTick = 0; // reset the next try
+ if(!protectedSetSocket(theHost, thePort, theIoType))
+ {
+ return;
+ }
+ else if(handle() < 0)// Quick test again to make sure its valid
+ {
+ return;
+ }
+ }
+ else // we were not able to update the handle yet so return, still invalid
+ {
+ return;
+ }
+ }
+ }
+ else// we were not able to update the handle yet so return, still invalid
+ {
+ return;
+ }
+ }
+
+ // poll for additional I/O connections
+ poll(10);
+
+ // handle any current connections and process the messages.
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockList(theIoListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::iterator iter = theIoList.begin();
+ while(iter!=theIoList.end())
+ {
+
+ osg::ref_ptr<ossimPlanetMessage> msg;
+ // perform IO
+ (*iter)->performIo();
+
+ // now pop any message for handling
+ //
+ while((msg=(*iter)->popMessage()).valid())
+ {
+ theInQueueMutex.lock();
+ if(enableFlag())
+ {
+ theInQueue.push(msg);
+ }
+ else
+ {
+ while(!theInQueue.empty())
+ {
+ theInQueue.pop();
+ }
+ }
+ theInQueueMutex.unlock();
+ }
+ // check to see if it's been marked as finished and if so remove from the list
+ if((*iter)->finishedFlag())
+ {
+ iter = theIoList.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+}
+
+osg::ref_ptr<ossimPlanetMessage> ossimPlanetIoSocketServerChannel::popMessage()
+{
+ osg::ref_ptr<ossimPlanetMessage> message;
+ if(!enableFlag()) return message;
+ theInQueueMutex.lock();
+ if(!theInQueue.empty())
+ {
+ message = theInQueue.front();
+ theInQueue.pop();
+ }
+ theInQueueMutex.unlock();
+
+ return message;
+}
+
+void ossimPlanetIoSocketServerChannel::setAutoReconnectFlag(bool flag)
+{
+ theAutoReconnectFlag = flag;
+}
+
+bool ossimPlanetIoSocketServerChannel::autoReconnectFlag()const
+{
+ return theAutoReconnectFlag;
+}
+
+void ossimPlanetIoSocketServerChannel::setAutoReconnectInterval(ossim_uint32 milliseconds)
+{
+ theAutoReconnectInterval = milliseconds;
+}
+
+ossim_uint32 ossimPlanetIoSocketServerChannel::autoReconnectInterval()const
+{
+ return theAutoReconnectInterval;
+}
+
+
+void ossimPlanetIoSocketServerChannel::handleRead (void) // for udp servers we can read
+{
+ netAddress addr ;
+ accept ( &addr ) ;
+ int h = getHandle();
+ if(h > -1)
+ {
+ theIoListMutex.lock();
+ if(!protectedFindHandle(h))
+ {
+ osg::ref_ptr<ossimPlanetIoSocket> socket = new ossimPlanetIoSocket();
+ socket->setIoDirection(ossimPlanetIoDirection_IN);
+ //socket->setAutoCloseOnPeerShutdownFlag(true);
+ socket->setAutoReconnectFlag(false);
+ socket->setHandle(getHandle());
+ if(enableFlag())
+ {
+ theIoList.push_back(socket.get());
+ }
+// std::cout << "List size = " << theIoList.size() << "\n";;
+ }
+ theIoListMutex.unlock();
+ }
+}
+
+void ossimPlanetIoSocketServerChannel::handleWrite (void)
+{
+#if 0
+ netAddress addr ;
+ accept ( &addr ) ;
+ int h = getHandle();
+ if(h > -1)
+ {
+ osg::ref_ptr<ossimPlanetIoSocket> socket = new ossimPlanetIoSocket();
+ socket->setIoDirection((ossimPlanetIoDirection)(ossimPlanetIoDirection_IN));
+ socket->setHandle(getHandle());
+ socket->closeIo();
+ }
+#endif
+}
+
+void ossimPlanetIoSocketServerChannel::handleAccept (void)// for tcp servers we can accept
+{
+ netAddress addr ;
+ int h = accept ( &addr ) ;
+ if(h != -1)
+ {
+ theIoListMutex.lock();
+ if(!protectedFindHandle(h))
+ {
+// std::cout << "Addind a io to the handleAccept " << h << "\n";
+ osg::ref_ptr<ossimPlanetIoSocket> socket = new ossimPlanetIoSocket();
+ socket->setIoDirection(ossimPlanetIoDirection_IN);
+ socket->setHandle(h);
+ socket->setBlockingFlag(false);
+ //socket->setAutoCloseOnPeerShutdownFlag(true);
+ socket->setAutoReconnectFlag(false);
+ if(enableFlag())
+ {
+ theIoList.push_back(socket.get());
+// std::cout << "Io list size === " << theIoList.size() << std::endl;
+ }
+ }
+ theIoListMutex.unlock();
+ }
+}
+
+bool ossimPlanetIoSocketServerChannel::protectedFindHandle(int h)const
+{
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::const_iterator it = theIoList.begin();
+
+ while(it!=theIoList.end())
+ {
+ ossimPlanetIoSocket* io = static_cast<ossimPlanetIoSocket*>((*it).get());
+ if(io->handle() == h)
+ {
+ return true;
+ }
+ ++it;
+ }
+
+ return false;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetIoThread.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetIoThread.cpp
new file mode 100644
index 0000000..8375215
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetIoThread.cpp
@@ -0,0 +1,748 @@
+#include <ossimPlanet/ossimPlanetIoThread.h>
+#include <ossimPlanet/ossimPlanetIoRoutableMessageHandler.h>
+#include <ossimPlanet/ossimPlanetIoSocket.h>
+#include <ossimPlanet/ossimPlanetIoSocketServerChannel.h>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+ossimPlanetIoThread::ossimPlanetIoThread()
+ :theDoneFlag(false),
+ theStartedFlag(false),
+ theStartCalledFlag(false),
+ thePauseFlag(false)
+{
+ setPathnameAndRegister(":io");
+ //addMessageHandler(new ossimPlanetIoRoutableMessageHandler);
+}
+
+void ossimPlanetIoThread::addIo(osg::ref_ptr<ossimPlanetIo> io,
+ bool autoStartFlag)
+{
+ theIoListMutex.lock();
+ theIoList.push_back(io);
+ theIoListMutex.unlock();
+ if(autoStartFlag&&!startedFlag())
+ {
+ start();
+ }
+}
+
+void ossimPlanetIoThread::execute(const ossimPlanetAction &a)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theDelayedExecutionMutex);
+ theDelayedExecution.push(a.clone());
+ if(!startedFlag())
+ {
+ start();
+ }
+}
+
+void ossimPlanetIoThread::sendMessage(osg::ref_ptr<ossimPlanetMessage> message, bool forceSendFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::iterator iter = theIoList.begin();
+ while(iter != theIoList.end())
+ {
+ (*iter)->pushMessage(message, forceSendFlag);
+ ++iter;
+ }
+}
+
+bool ossimPlanetIoThread::sendMessage(const ossimString& searchName,
+ osg::ref_ptr<ossimPlanetMessage> message,
+ bool forceSendFlag)
+{
+ bool result = false;
+ osg::ref_ptr<ossimPlanetIo> io = findIo(searchName);
+ if(io.valid())
+ {
+ result = true;
+ io->pushMessage(message, forceSendFlag);
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetIo> ossimPlanetIoThread::removeIoGivenSearchString(const ossimString& searchString)
+{
+ osg::ref_ptr<ossimPlanetIo> result = 0;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::iterator iter = theIoList.begin();
+ ossimString tempSearchString;
+ while(iter != theIoList.end())
+ {
+ (*iter)->searchName(tempSearchString);
+ if(tempSearchString == searchString)
+ {
+ result = (*iter);
+ theIoList.erase(iter);
+
+ return result;
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetIo> ossimPlanetIoThread::findIo(const ossimString& searchString)
+{
+ osg::ref_ptr<ossimPlanetIo> result = 0;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::iterator iter = theIoList.begin();
+ ossimString tempSearchString;
+ while(iter != theIoList.end())
+ {
+ (*iter)->searchName(tempSearchString);
+ if(tempSearchString == searchString)
+ {
+ return (*iter);
+ }
+ ++iter;
+ }
+
+ return result;
+}
+
+const osg::ref_ptr<ossimPlanetIo> ossimPlanetIoThread::findIo(const ossimString& searchString)const
+{
+ const osg::ref_ptr<ossimPlanetIo> result = 0;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::const_iterator iter = theIoList.begin();
+ ossimString tempSearchString;
+ while(iter != theIoList.end())
+ {
+ (*iter)->searchName(tempSearchString);
+ if(tempSearchString == searchString)
+ {
+ return (*iter).get();
+ }
+ ++iter;
+ }
+
+ return result;
+}
+
+
+bool ossimPlanetIoThread::removeIo(osg::ref_ptr<ossimPlanetIo> io)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theIoListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::iterator iter = theIoList.begin();
+ ossimString tempSearchString;
+ while(iter != theIoList.end())
+ {
+ if((*iter).get() == io.get())
+ {
+ theIoList.erase(iter);
+ return true;
+ }
+ ++iter;
+ }
+ return false;
+}
+
+void ossimPlanetIoThread::run()
+{
+ if(startedFlag()) return;
+ setStartedFlag(theStartedFlag);
+ setDoneFlag(false);
+
+ while(!doneFlag())
+ {
+ {
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theLoopMutex);
+ if(!pauseFlag())
+ {
+ theDelayedExecutionMutex.lock();
+ while(!theDelayedExecution.empty())
+ {
+ delayedExecute(*theDelayedExecution.front());
+ theDelayedExecution.pop();
+ }
+ theDelayedExecutionMutex.unlock();
+ theIoListMutex.lock();
+ std::vector<osg::ref_ptr<ossimPlanetIo> >::iterator iter = theIoList.begin();
+ while(iter != theIoList.end())
+ {
+ osg::ref_ptr<ossimPlanetMessage> msg;
+ (*iter)->performIo();
+
+ while((msg = (*iter)->popMessage()).valid())
+ {
+ handleMessage(msg);
+ }
+ msg = 0;
+ if((*iter)->finishedFlag())
+ {
+ iter = theIoList.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ theIoListMutex.unlock();
+ }
+ }
+ microSleep(5000);
+ }
+ setDoneFlag(true);
+ setStartedFlag(false);
+ setStartCalledFlag(false);
+}
+
+int ossimPlanetIoThread::cancel()
+{
+ setDoneFlag(true);
+ return OpenThreads::Thread::cancel();
+}
+
+bool ossimPlanetIoThread::addMessageHandler(osg::ref_ptr<ossimPlanetIoMessageHandler> handler)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theMessageHandlerList.size(); ++idx)
+ {
+ if(handler.get()==theMessageHandlerList[idx].get())
+ {
+ return false;
+ }
+ }
+ theMessageHandlerList.push_back(handler.get());
+ return true;
+}
+
+bool ossimPlanetIoThread::removeMessageHandler(osg::ref_ptr<ossimPlanetIoMessageHandler> handler)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerListMutex);
+ ossimPlanetIoThread::MessageHandlerListType::iterator iter = theMessageHandlerList.begin();
+
+ while(iter != theMessageHandlerList.end())
+ {
+ if((*iter).get() == handler.get())
+ {
+ theMessageHandlerList.erase(iter);
+ return true;
+ }
+ ++iter;
+ }
+
+ return false;
+}
+
+bool ossimPlanetIoThread::removeMessageHandler(const ossimString& handlerName)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerListMutex);
+ ossimPlanetIoThread::MessageHandlerListType::iterator iter = theMessageHandlerList.begin();
+
+ while(iter != theMessageHandlerList.end())
+ {
+ if((*iter)->name() == handlerName)
+ {
+ theMessageHandlerList.erase(iter);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+ossim_uint32 ossimPlanetIoThread::ioCount()const
+{
+ return theIoList.size();
+}
+
+void ossimPlanetIoThread::clearIo()
+{
+ theIoListMutex.lock();
+ theIoList.clear();
+ theIoListMutex.unlock();
+}
+
+bool ossimPlanetIoThread::startedFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theStartedFlag;
+}
+
+void ossimPlanetIoThread::setStartedFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theStartedFlag = flag;
+}
+
+bool ossimPlanetIoThread::doneFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theDoneFlag;
+}
+
+void ossimPlanetIoThread::setDoneFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theDoneFlag = flag;
+}
+
+void ossimPlanetIoThread::setPauseFlag(bool flag, bool waitTilPaused)
+{
+ if(waitTilPaused)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(theLoopMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(thePropertyMutex);
+ thePauseFlag = flag;
+ }
+ else
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ thePauseFlag = flag;
+ }
+}
+
+bool ossimPlanetIoThread::pauseFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return thePauseFlag;
+}
+
+bool ossimPlanetIoThread::startCalledFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theStartCalledFlag;
+}
+
+void ossimPlanetIoThread::setStartCalledFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theStartCalledFlag = flag;
+}
+
+void ossimPlanetIoThread::start()
+{
+ if(startCalledFlag())
+ {
+ return;
+ }
+ setStartCalledFlag(true);
+ OpenThreads::Thread::start();
+}
+
+void ossimPlanetIoThread::handleMessage(osg::ref_ptr<ossimPlanetMessage> msg)
+{
+ ossim_uint32 idx = 0;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerListMutex);
+ for(idx = 0; idx < theMessageHandlerList.size();++idx)
+ {
+ if(theMessageHandlerList[idx]->handleMessage(msg))
+ {
+ return;
+ }
+ }
+}
+
+void ossimPlanetIoThread::delayedXmlExecute(const ossimPlanetXmlAction& a)
+{
+ ossimString command = a.command();
+ if(command == "SendMessage")
+ {
+ if(a.xmlNode().valid())
+ {
+ ossimString id = a.xmlNode()->getAttributeValue("id");
+ ossimString searchName = a.xmlNode()->getAttributeValue("ioTargetId");
+ ossimString forceSend = a.xmlNode()->getAttributeValue("forceSend");
+ bool forceSendFlag = forceSend.empty()?false:forceSend.toBool();
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ for(idx = 0;idx<children.size();++idx)
+ {
+ std::ostringstream out;
+ out << *children[idx] << std::endl;
+ if(searchName.empty())
+ {
+ sendMessage(new ossimPlanetMessage(id, ossimString(out.str())), forceSendFlag);
+ }
+ else
+ {
+ sendMessage(searchName, new ossimPlanetMessage(id, ossimString(out.str())), forceSendFlag);
+ }
+ }
+ }
+ }
+ else if(command == "Set")
+ {
+ if(a.xmlNode().valid())
+ {
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ ossimString id = a.xmlNode()->getAttributeValue("id");
+ for(idx = 0;idx<children.size();++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ if(tag == "connectionHeader")
+ {
+ ossimString headerValue = children[idx]->getText();
+ osg::ref_ptr<ossimPlanetIo> io = findIo(id);
+ if(io.valid())
+ {
+ std::vector<char> value(headerValue.begin(),
+ headerValue.end());
+ io->setConnectionHeader(new ossimPlanetMessage("", ossimString(headerValue)));
+ }
+ }
+ }
+ }
+ }
+ else if((command == "Remove")||
+ (command == "Close"))
+ {
+ if(a.xmlNode().valid())
+ {
+ ossimString id = a.xmlNode()->getAttributeValue("id");
+ removeIoGivenSearchString(id);
+ }
+ }
+ else if(command == "Open")
+ {
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ for(idx = 0;idx<children.size();++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ if(tag == "ServerSocket")
+ {
+ ossimString name = children[idx]->getChildTextValue("name");
+ ossimString ip = children[idx]->getChildTextValue("ip");
+ ossimString port = children[idx]->getChildTextValue("port");
+ ossimString portType = children[idx]->getChildTextValue("portType");
+ ossimString terminator = children[idx]->getChildTextValue("terminator");
+ if(name.empty())
+ {
+ name = ip;
+ }
+#if 0
+ char terminatorChar = '\0';
+ if((terminator == "nul")||
+ (terminator == "eos"))
+ {
+ terminatorChar = '\0';
+ }
+ else if(terminator == "eol")
+ {
+ terminatorChar = '\n';
+ }
+#endif
+ if(portType.empty())
+ {
+ portType = "tcp";
+ }
+ if(!port.empty())
+ {
+
+ }
+ ossimPlanetIoSocketServerChannel* channel = new ossimPlanetIoSocketServerChannel;
+ channel->setName(name);
+ if(channel->setSocket(ip,
+ port.toInt32(),
+ portType))
+ {
+ addIo(channel);
+ }
+ else
+ {
+ delete channel;
+ channel = 0;
+ }
+ }
+ else if(tag == "ClientSocket")
+ {
+ osg::ref_ptr<ossimPlanetIoSocket> socket = 0;
+ ossimString name = children[idx]->getChildTextValue("name");
+ ossimString ip = children[idx]->getChildTextValue("ip");
+ ossimString port = children[idx]->getChildTextValue("port");
+ ossimString portType = children[idx]->getChildTextValue("portType");
+ ossimString terminator = children[idx]->getChildTextValue("terminator");
+ ossimString autoReconnectFlag = children[idx]->getChildTextValue("autoReconnectFlag");
+ char terminatorChar = '\0';
+ if((terminator == "nul")||
+ (terminator == "eos"))
+ {
+ terminatorChar = '\0';
+ }
+ else if(terminator == "eol")
+ {
+ terminatorChar = '\n';
+ }
+ if(portType.empty())
+ {
+ portType = "tcp";
+ }
+ if(name.empty())
+ {
+ name = ip;
+ }
+ if(autoReconnectFlag.empty())
+ {
+ autoReconnectFlag = "true";
+ }
+ if(!ip.empty() && !port.empty())
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(name + ":" + port);
+ if(!io.valid())
+ {
+ socket = new ossimPlanetIoSocket();
+ socket->setName(name);
+ socket->setTerminator(terminatorChar);
+ socket->setSocket(ip, port.toInt32(), portType);
+ socket->setBlockingFlag(false);
+ socket->setAutoReconnectFlag(autoReconnectFlag.toBool());
+ }
+ }
+ if(socket.valid())
+ {
+ addIo(socket.get());
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetIoThread::delayedExecute(const ossimPlanetAction &action)
+{
+ const ossimPlanetXmlAction* xmlAction = action.toXmlAction();
+
+ if(xmlAction)
+ {
+ delayedXmlExecute(*xmlAction);
+ return;
+ }
+
+ const ossimPlanetDestinationCommandAction* a = action.toDestinationCommandAction();
+ // for now only support :destination command <args> style actions;
+ if(!a) return;
+ ossimString command = a->command();
+ if(command == "openServerSocket")
+ {
+ if(a->argCount() == 2) // name and port
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(a->arg(1) + ":" + a->arg(2));
+ if(!io.valid())
+ {
+ ossimPlanetIoSocketServerChannel* channel = new ossimPlanetIoSocketServerChannel;
+ channel->setName(a->arg(1));
+ if(channel->setSocket("",
+ ossimString(a->arg(2)).toUInt32(),
+ "tcp"))
+ {
+ addIo(channel);
+ }
+ else
+ {
+ delete channel;
+ }
+ }
+ }
+ else if(a->argCount() == 3) // <name> <port> <tcp or udp>
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(a->arg(1) + ":" + a->arg(2));
+ if(!io.valid())
+ {
+ osg::ref_ptr<ossimPlanetIoSocketServerChannel> channel = new ossimPlanetIoSocketServerChannel;
+ channel->setName(a->arg(1));
+ if(channel->setSocket("",
+ ossimString(a->arg(2)).toUInt32(),
+ a->arg(3)))
+ {
+ addIo(channel.get());
+ }
+ }
+ }
+ }
+ // Can have the form of:
+ // {ClientSocket {Name <name>} {Port <port>} {Ip <ip>} {Type <type>} {Terminator <eos|eol>} }
+ else if(command == "openConnection")
+ {
+ ossim_uint32 idx = 0;
+ ossimString objectName;
+ ossimString objectArg;
+ for(idx = 1; idx <= a->argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName, objectArg, a->arg(idx)))
+ {
+ if(objectName == "ClientSocket")
+ {
+ osg::ref_ptr<ossimPlanetIoSocket> socket = 0;
+ ossimString name;
+ ossimString port;
+ ossimString ip;
+ ossimString type = "tcp";
+ char terminator = '\0';
+ ossimPlanetDestinationCommandAction nestedAction(": ClientSocket " + objectArg);
+ ossim_uint32 nestedIdx = 1;
+ for(;nestedIdx <= nestedAction.argCount(); ++nestedIdx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName, objectArg, nestedAction.arg(nestedIdx)))
+ {
+ if(objectName == "Port")
+ {
+ port = objectArg;
+ }
+ else if(objectName == "Ip")
+ {
+ ip = objectArg;
+ }
+ else if(objectName == "PortType")
+ {
+ type = objectArg;
+ }
+ else if(objectName == "Type")
+ {
+ std::cout << "Obsolete object arg. Please use PortType instead of Type" << std::endl;
+ type = objectArg;
+ }
+ else if(objectName == "Name")
+ {
+ name = objectArg;
+ }
+ else if(objectName == "Terminator")
+ {
+ if((objectArg == "nul")||
+ (objectArg == "eos"))
+ {
+ terminator = '\0';
+ }
+ else if(objectArg == "eol")
+ {
+ terminator = '\n';
+ }
+ }
+ }
+ }// end for nested action
+
+ if(!ip.empty() && !port.empty())
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(name + ":" + port);
+ if(!io.valid())
+ {
+ socket = new ossimPlanetIoSocket();
+ socket->setName(name);
+ socket->setTerminator(terminator);
+ if(!socket->setSocket(ip, port.toInt32(), type))
+ {
+ socket = 0;
+ }
+ }
+ }
+
+ if(socket.valid())
+ {
+ addIo(socket.get());
+ }
+ }// end if ClientSocket
+ }
+ }
+ }
+ else if(command == "openClientSocket")
+ {
+ // This is a bidirectional client socket
+ osg::ref_ptr<ossimPlanetIoSocket> socket = 0;
+ if(a->argCount() == 3) // default tcp
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(a->arg(1) + ":" + a->arg(3));
+ if(!io.valid())
+ {
+ socket = new ossimPlanetIoSocket();
+ socket->setName(a->arg(1));
+ if(!socket->setSocket(a->arg(2),
+ ossimString(a->arg(3)).toInt32(),
+ "tcp"))
+ {
+ socket = 0;
+ }
+ }
+ }
+ else if(a->argCount() == 4) // specify the type
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(a->arg(1) + ":" + a->arg(3));
+ if(!io.valid())
+ {
+ socket = new ossimPlanetIoSocket();
+ socket->setName(a->arg(1));
+
+ if(!socket->setSocket(a->arg(2),//host
+ ossimString(a->arg(3)).toInt32(), // port
+ a->arg(4)))
+ {
+ socket = 0;
+ }
+ }
+ }
+ if(socket.valid())
+ {
+ addIo(socket.get());
+ }
+ }
+ else if(command == "sendMessage")
+ {
+ // check for form <search name> <message>
+ if(a->argCount() == 2)
+ {
+ sendMessage(a->arg(1),
+ new ossimPlanetMessage("", a->arg(2)));
+ }
+ else if(a->argCount() == 1)
+ {
+ sendMessage(new ossimPlanetMessage("", a->arg(1)));
+ }
+ }
+ else if(command == "removeIo")
+ {
+ if(a->argCount() == 1)
+ {
+ removeIoGivenSearchString(a->arg(1));
+ }
+ }
+ else if(command == "changeName")
+ {
+ if(a->argCount() == 2)
+ {
+ // need form of <search name> <new name>
+ osg::ref_ptr<ossimPlanetIo> io = findIo(a->arg(1));
+ if(io.valid())
+ {
+ io->setName(a->arg(2));
+ }
+ }
+ }
+ else if(command == "setTerminator")
+ {
+ if(a->argCount() == 2)
+ {
+ osg::ref_ptr<ossimPlanetIo> io = findIo(a->arg(1));
+ if(io.valid())
+ {
+ ossimString terminatorType = a->arg(2);
+
+ char terminator;
+ if(terminatorType == "eos")
+ {
+ terminator = '\0';
+ }
+ else if(terminatorType == "eol")
+ {
+ terminator = '\n';
+ }
+ else
+ {
+ terminator = *(terminatorType.begin());
+ }
+ io->setTerminator(terminator);
+ }
+ }
+ else if(a->argCount() == 1)
+ {
+ }
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetJpegImage.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetJpegImage.cpp
new file mode 100644
index 0000000..113b46e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetJpegImage.cpp
@@ -0,0 +1,363 @@
+#include <ossimPlanet/ossimPlanetJpegImage.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <iostream>
+#include <fstream>
+
+extern "C" {
+#include <jpeglib.h>
+#include <setjmp.h>
+#define JPEG_IO_BUFFER_SIZE 2048
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ JOCTET* buffer; /* start of buffer */
+ std::istream *stream;
+} ossimPlanet_source_mgr;
+typedef struct {
+ struct jpeg_destination_mgr pub;
+
+ std::ostream *stream;
+ JOCTET * buffer;
+} ossimPlanet_destination_mgr;
+
+typedef ossimPlanet_destination_mgr * ossimPlanet_dest_ptr;
+
+
+typedef ossimPlanet_source_mgr * ossimPlanet_src_ptr;
+
+
+static void ossimPlanet_init_source ( j_decompress_ptr )
+{
+}
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
+
+static void init_destination (j_compress_ptr cinfo)
+{
+ ossimPlanet_dest_ptr dest = (ossimPlanet_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * sizeof(JOCTET));
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+static boolean empty_output_buffer (j_compress_ptr cinfo)
+{
+ ossimPlanet_dest_ptr dest = (ossimPlanet_dest_ptr) cinfo->dest;
+
+ dest->stream->write((char*)dest->buffer, OUTPUT_BUF_SIZE);
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+ return TRUE;
+}
+
+static void term_destination (j_compress_ptr cinfo)
+{
+ ossimPlanet_dest_ptr dest = (ossimPlanet_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+ /* Write any data remaining in the buffer */
+ if (datacount > 0)
+ dest->stream->write((char*)dest->buffer, datacount);
+}
+
+static boolean ossimPlanet_fill_input_buffer ( j_decompress_ptr cinfo )
+{
+ ossimPlanet_src_ptr src = (ossimPlanet_src_ptr) cinfo->src;
+
+ src->pub.next_input_byte = src->buffer;
+ std::streamsize start = src->stream->tellg();
+ src->stream->read((char*)(src->buffer),
+ JPEG_IO_BUFFER_SIZE).tellg();
+ std::streamsize end = src->stream->tellg();
+
+ src->pub.bytes_in_buffer = end - start;
+
+ if (src->pub.bytes_in_buffer == 0) // check for end-of-stream
+ {
+ // Insert a fake EOI marker
+ src->buffer[0] = 0xFF;
+ src->buffer[1] = JPEG_EOI;
+ src->pub.bytes_in_buffer = 2;
+ }
+ return TRUE;
+}
+
+static void ossimPlanet_skip_input_data ( j_decompress_ptr cinfo, long num_bytes )
+{
+ if (num_bytes > 0)
+ {
+ ossimPlanet_src_ptr src = (ossimPlanet_src_ptr) cinfo->src;
+
+ while (num_bytes > (long)src->pub.bytes_in_buffer)
+ {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ src->pub.fill_input_buffer(cinfo);
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+static void ossimPlanet_term_source ( j_decompress_ptr cinfo )
+{
+ ossimPlanet_src_ptr src = (ossimPlanet_src_ptr) cinfo->src;
+
+ if (src->pub.bytes_in_buffer > 0)
+ src->stream->seekg(-(long)src->pub.bytes_in_buffer, std::ios_base::cur);
+ delete[] src->buffer;
+}
+
+
+// JPEG error manager:
+
+struct ossimPlanet_error_mgr {
+ struct jpeg_error_mgr pub; /* "public" fields */
+
+ jmp_buf setjmp_buffer; /* for return to caller */
+};
+
+typedef struct ossimPlanet_error_mgr * ossimPlanet_error_ptr;
+
+/*
+ * Here's the routine that will replace the standard error_exit method:
+ */
+
+static void ossimPlanet_error_exit (j_common_ptr cinfo)
+{
+ /* cinfo->err really points to a ossimPlanet_error_mgr struct, so coerce pointer */
+ ossimPlanet_error_ptr myerr = (ossimPlanet_error_ptr) cinfo->err;
+
+ /* Always display the message. */
+ /* We could postpone this until after returning, if we chose. */
+ if (cinfo->err->output_message) (*cinfo->err->output_message) (cinfo);
+
+ /* Return control to the setjmp point */
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+
+void ossimPlanet_jpeg_io_src( j_decompress_ptr cinfo, std::istream& infile )
+{
+ ossimPlanet_src_ptr src;
+
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(ossimPlanet_source_mgr));
+ }
+ src = (ossimPlanet_src_ptr) cinfo->src;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->buffer = new JOCTET[JPEG_IO_BUFFER_SIZE];
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+ src->stream = &infile;
+
+ src->pub.init_source = ossimPlanet_init_source;
+ src->pub.fill_input_buffer = ossimPlanet_fill_input_buffer;
+ src->pub.skip_input_data = ossimPlanet_skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = ossimPlanet_term_source;
+}
+
+static void ossimPlanet_init_destination (j_compress_ptr cinfo)
+{
+ ossimPlanet_dest_ptr dest = (ossimPlanet_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * sizeof(JOCTET));
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+static boolean ossimPlanet_empty_output_buffer (j_compress_ptr cinfo)
+{
+ ossimPlanet_dest_ptr dest = (ossimPlanet_dest_ptr) cinfo->dest;
+
+ dest->stream->write((char*)(dest->buffer), OUTPUT_BUF_SIZE);
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+ return TRUE;
+}
+
+static void ossimPlanet_term_destination (j_compress_ptr cinfo)
+{
+ ossimPlanet_dest_ptr dest = (ossimPlanet_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+ /* Write any data remaining in the buffer */
+ if (datacount > 0)
+ dest->stream->write((char*)(dest->buffer), datacount);
+}
+
+static void ossimPlanet_jpeg_io_dest (j_compress_ptr cinfo, std::ostream& outfile)
+{
+ ossimPlanet_dest_ptr dest;
+
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(ossimPlanet_destination_mgr));
+ }
+
+ dest = (ossimPlanet_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = ossimPlanet_init_destination;
+ dest->pub.empty_output_buffer = ossimPlanet_empty_output_buffer;
+ dest->pub.term_destination = ossimPlanet_term_destination;
+ dest->stream = &outfile;
+}
+
+
+
+ossimPlanetJpegImage::ossimPlanetJpegImage()
+{
+}
+
+ossimPlanetJpegImage::~ossimPlanetJpegImage()
+{
+}
+
+bool ossimPlanetJpegImage::loadFile(std::istream& inputStream,
+ ossimPlanetImage& image)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct ossimPlanet_error_mgr jerr;
+ JSAMPARRAY tempbuf;
+ unsigned char *ptr;
+ unsigned stride;
+
+ cinfo.err = jpeg_std_error( &jerr.pub );
+ jerr.pub.error_exit = ossimPlanet_error_exit;
+
+ cinfo.err->output_message=NULL;
+
+ /* Establish the setjmp return context for ossimPlanet_error_exit to use. */
+ if (setjmp(jerr.setjmp_buffer)) {
+ /* If we get here, the JPEG code has signaled an error.
+ * We need to clean up the JPEG object, close the input file, and return.
+ */
+ (cinfo.src->term_source)(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ return FALSE;
+ }
+
+ jpeg_create_decompress( &cinfo );
+ ossimPlanet_jpeg_io_src( &cinfo, inputStream );
+ jpeg_read_header( &cinfo, TRUE );
+ cinfo.out_color_space = JCS_RGB;
+ jpeg_start_decompress( &cinfo );
+
+ image.allocateImage(cinfo.image_width,
+ cinfo.image_height,
+ 1,
+ GL_RGB,
+ GL_UNSIGNED_BYTE);
+// image.create(cinfo.image_width, cinfo.image_height);
+ ptr = image.data();
+ stride = cinfo.output_width * 3;
+ tempbuf = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 );
+
+ while ( cinfo.output_scanline < cinfo.output_height )
+ {
+ jpeg_read_scanlines( &cinfo, tempbuf, 1 );
+ memcpy( ptr, tempbuf[0], stride );
+ ptr += stride;
+ }
+ jpeg_finish_decompress( &cinfo );
+ jpeg_destroy_decompress( &cinfo );
+
+ return TRUE;
+}
+
+bool ossimPlanetJpegImage::saveFile( std::ostream& stream,
+ ossimPlanetImage &image,
+ bool verbose )
+{
+ struct jpeg_compress_struct cinfo;
+ struct ossimPlanet_error_mgr jerr;
+ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+ JSAMPLE *image_buffer;
+ int stride; /* physical row width in image buffer */
+
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = ossimPlanet_error_exit;
+
+ if (!verbose) cinfo.err->output_message=NULL;
+
+ /* Establish the setjmp return context for my_error_exit to use. */
+ if (setjmp(jerr.setjmp_buffer))
+ {
+ /* If we get here, the JPEG code has signaled an error.
+ * We need to clean up the JPEG object, close the input file, and return.
+ */
+ jpeg_destroy_compress(&cinfo);
+ return false;
+ }
+
+ jpeg_create_compress(&cinfo);
+ ossimPlanet_jpeg_io_dest(&cinfo, stream);
+
+ cinfo.image_width = image.getWidth();
+ cinfo.image_height = image.getHeight();
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ jpeg_set_defaults(&cinfo);
+
+ // TODO: 3rd parameter is force_baseline, what value should this be?
+ // Code says: "If force_baseline is TRUE, the computed quantization table entries
+ // are limited to 1..255 for JPEG baseline compatibility."
+ // 'Quality' is a number between 0 (terrible) and 100 (very good).
+ // The default (in jcparam.c, jpeg_set_defaults) is 75,
+ // and force_baseline is TRUE.
+ jpeg_set_quality(&cinfo, 100, TRUE);
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ stride = cinfo.image_width * 3; /* JSAMPLEs per row in image_buffer */
+ image_buffer = image.data();
+ ossim_uint32 scanlineTemp = cinfo.next_scanline;
+ while (cinfo.next_scanline < cinfo.image_height)
+ {
+ row_pointer[0] = &image_buffer[cinfo.next_scanline * stride];
+ jpeg_write_scanlines( &cinfo, row_pointer, 1 );
+ if(scanlineTemp == cinfo.next_scanline)
+ {
+ ++cinfo.next_scanline;
+ }
+ scanlineTemp = cinfo.next_scanline;
+ }
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+
+ return true;
+}
+
+bool ossimPlanetJpegImage::loadFile(std::string& inputFile,
+ ossimPlanetImage& image)
+{
+ std::ifstream in(inputFile.c_str(),
+ std::ios::in|std::ios::binary);
+ if(in)
+ {
+ return loadFile(in, image);
+ }
+ return false;
+}
+
+bool ossimPlanetJpegImage::saveFile(std::string& outputFile,
+ ossimPlanetImage& image)
+{
+ std::ofstream out(outputFile.c_str(),
+ std::ios::out|std::ios::binary);
+ if(out)
+ {
+ return saveFile(out, image);
+ }
+ return false;
+}
+
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetKml.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetKml.cpp
new file mode 100644
index 0000000..e26db79
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetKml.cpp
@@ -0,0 +1,2818 @@
+#include <ossimPlanet/ossimPlanetKml.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetSetup.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <wms/wmsCurlMemoryStream.h>
+
+#include <queue>
+#ifdef OSSIMPLANET_HAS_LIBZ
+#include <ossimPlanet/unzip.h>
+#endif
+
+static std::istream& kmlskipws(std::istream& in)
+{
+ int c = in.peek();
+ while(!in.fail()&&
+ ((c == ' ') ||
+ (c == '\t') ||
+ (c == '\n')||
+ (c == '\r')))
+ {
+ in.ignore(1);
+ c = in.peek();
+ }
+
+ return in;
+}
+
+static void kmlReadCoordinates(ossimPlanetKmlGeometry::PointListType& pointListResult,
+ std::istream& in)
+{
+ bool pointIsGood = true;
+ osg::Vec3d point;
+ while(!in.fail())
+ {
+ in >>point[0]>>kmlskipws;
+ in.ignore();
+ in >>point[1]>>kmlskipws;
+
+ // if we get at least 2 values then we are good
+ pointIsGood = !in.fail();
+ point[2] = 0.0;
+ if(in.peek() == ',')
+ {
+ in.ignore();
+ in >> point[2];
+ }
+
+ in>>kmlskipws;
+
+ if(in.peek() == ',')
+ {
+ in.ignore(); // we will suport separated by commas even though the spec says spaces
+ }
+ if(pointIsGood)
+ {
+ pointListResult.push_back(point);
+ }
+ }
+}
+
+static void kmlReadCoordinates(ossimPlanetKmlGeometry::PointListType& pointListResult,
+ const ossimString& inString)
+{
+ if(inString.empty()) return;
+ std::vector<ossimString> points;
+ inString.split(points, " \n\t\r");
+ ossim_uint32 idx = 0;
+ osg::Vec3d point;
+ for(idx = 0; idx < points.size(); ++idx)
+ {
+ std::vector<ossimString> coordinate;
+ points[idx].split(coordinate, ",");
+ if(coordinate.size() >= 2)
+ {
+ point[0] = coordinate[0].toDouble();
+ point[1] = coordinate[1].toDouble();
+ if(coordinate.size() > 2)
+ {
+ point[2] = coordinate[2].toDouble();
+ }
+ else
+ {
+ point[2] = 0.0;
+ }
+ pointListResult.push_back(point);
+ }
+ }
+ //std::istringstream in(inString);
+ //kmlReadCoordinates(pointListResult, in);
+}
+
+ossimPlanetKmlObjectRegistry* ossimPlanetKmlObjectRegistry::theInstance = 0;
+ossimPlanetKmlObjectRegistry::ossimPlanetKmlObjectRegistry()
+{
+ theInstance = this;
+}
+
+
+ossimPlanetKmlObjectRegistry* ossimPlanetKmlObjectRegistry::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetKmlObjectRegistry;
+ }
+
+ return theInstance;
+}
+ossimPlanetKmlObject* ossimPlanetKmlObjectRegistry::newObject(const ossimString& tag)const
+{
+ if(tag == "Document")
+ {
+ return new ossimPlanetKmlDocument;
+ }
+ else if(tag == "Placemark")
+ {
+ return new ossimPlanetKmlPlacemark;
+ }
+ else if(tag == "Folder")
+ {
+ return new ossimPlanetKmlFolder;
+ }
+ else if(tag == "Icon")
+ {
+ return new ossimPlanetKmlIcon;
+ }
+ else if(tag == "LatLonBox")
+ {
+ return new ossimPlanetKmlLatLonBox;
+ }
+ else if(tag == "LatLonAltBox")
+ {
+ return new ossimPlanetKmlLatLonAltBox;
+ }
+ else if(tag == "GroundOverlay")
+ {
+ return new ossimPlanetKmlGroundOverlay;
+ }
+ else if(tag == "ScreenOverlay")
+ {
+ return new ossimPlanetKmlScreenOverlay;
+ }
+ else if(tag == "Point")
+ {
+ return new ossimPlanetKmlPoint;
+ }
+ else if(tag == "NetworkLink")
+ {
+ return new ossimPlanetKmlNetworkLink;
+ }
+ else if(tag == "Orientation")
+ {
+ return new ossimPlanetKmlOrientation;
+ }
+ else if(tag == "Location")
+ {
+ return new ossimPlanetKmlLocation;
+ }
+ else if(tag == "Scale")
+ {
+ return new ossimPlanetKmlScale;
+ }
+ else if(tag == "Lod")
+ {
+ return new ossimPlanetKmlLod;
+ }
+ else if(tag == "Region")
+ {
+ return new ossimPlanetKmlRegion;
+ }
+ else if(tag == "BalloonStyle")
+ {
+ return new ossimPlanetKmlBalloonStyle;
+ }
+ else if(tag == "Style")
+ {
+ return new ossimPlanetKmlStyle;
+ }
+ else if(tag == "StyleMap")
+ {
+ return new ossimPlanetKmlStyleMap;
+ }
+ ossimPlanetKmlObject* obj = newTimePrimitive(tag);
+ if(obj)
+ {
+ return obj;
+ }
+ obj = newColorStyle(tag);
+ if(obj)
+ {
+ return obj;
+ }
+ return newGeometry(tag);
+}
+
+ossimPlanetKmlObject* ossimPlanetKmlObjectRegistry::newGeometry(const ossimString& tag)const
+{
+ if(tag == "Point")
+ {
+ return new ossimPlanetKmlPoint;
+ }
+ else if(tag == "LineString")
+ {
+ return new ossimPlanetKmlLineString;
+ }
+ else if(tag == "LinearRing")
+ {
+ return new ossimPlanetKmlLinearRing;
+ }
+ else if(tag == "Polygon")
+ {
+ return new ossimPlanetKmlPolygon;
+ }
+ else if((tag == "MultiGeometry")||
+ (tag == "GeometryCollection"))
+ {
+ return new ossimPlanetKmlMultiGeometry;
+ }
+ else if(tag == "Model")
+ {
+ return new ossimPlanetKmlModel;
+ }
+ return 0;
+}
+
+ossimPlanetKmlObject* ossimPlanetKmlObjectRegistry::newColorStyle(const ossimString& tag)const
+{
+ if(tag == "LineStyle")
+ {
+ return new ossimPlanetKmlLineStyle;
+ }
+ else if(tag == "PolyStyle")
+ {
+ return new ossimPlanetKmlPolyStyle;
+ }
+ else if(tag == "IconStyle")
+ {
+ return new ossimPlanetKmlIconStyle;
+ }
+ else if(tag == "LabelStyle")
+ {
+ return new ossimPlanetKmlLabelStyle;
+ }
+ return 0;
+}
+
+ossimPlanetKmlObject* ossimPlanetKmlObjectRegistry::newTimePrimitive(const ossimString& tag)const
+{
+ if(tag == "TimeSpan")
+ {
+ return new ossimPlanetKmlTimeSpan;
+ }
+ else if(tag == "TimeStamp")
+ {
+ return new ossimPlanetKmlTimeStamp;
+ }
+
+ return 0;
+}
+
+ossimPlanetKmlObject* ossimPlanetKmlObjectRegistry::newObject(const ossimXmlNode* tag)const
+{
+ if(tag)
+ {
+ return newObject(tag->getTag());
+
+ }
+
+ return 0;
+}
+
+bool ossimPlanetKmlObject::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ if(!xmlNode.valid()) return false;
+
+ xmlNode->getAttributeValue(theId, "id");
+ xmlNode->getAttributeValue(theTargetId, "targetId");
+
+ return true;
+}
+
+void ossimPlanetKmlObject::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ if(!xmlNode.valid()) return;
+ if(!theId.empty())
+ {
+ xmlNode->addAttribute("id", theId);
+ }
+ if(!theTargetId.empty())
+ {
+ xmlNode->addAttribute("targetId", theTargetId);
+ }
+}
+
+ossimPlanetKmlObject* ossimPlanetKmlObject::getRoot(ossimPlanetKmlObject* start)
+{
+ ossimPlanetKmlObject* root = start;
+
+ if(!root) return 0;
+ while(root->getParent()) root = root->getParent();
+ return root;
+}
+
+ossimFilename ossimPlanetKmlObject::getKmlFile()const
+{
+ if(getParent()) return getParent()->getKmlFile();
+
+ return "";
+}
+
+const ossimPlanetKmlObject* ossimPlanetKmlObject::getRoot(const ossimPlanetKmlObject* start)
+{
+ const ossimPlanetKmlObject* root = start;
+
+ if(!root) return 0;
+ while(root->getParent()) root = root->getParent();
+ return root;
+}
+
+
+ossimFilename ossimPlanetKmlObject::getCacheLocation(bool sharedLocationFlag)const
+{
+ const ossimPlanetKmlObject* kmlObject = getRoot(this);
+
+ const ossimPlanetKml* kml = dynamic_cast<const ossimPlanetKml*>(kmlObject);
+
+ if(kml)
+ {
+ return kml->getCacheLocation(sharedLocationFlag);
+ }
+
+ if(sharedLocationFlag)
+ {
+ ossimFilename sharedDir = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ sharedDir = sharedDir.dirCat("kml");
+ if(!sharedDir.exists())
+ {
+ sharedDir.createDirectory();
+ }
+ return sharedDir;
+ }
+ return "";
+}
+
+bool ossimPlanetKmlBalloonStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+
+ ossim_uint32 idx;
+ ossim_uint32 upper=childNodes.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "bgColor")
+ {
+ theBackgroundColor = childNodes[idx]->getText();
+ theBackgroundColor = theBackgroundColor.trim();
+ }
+ else if(tag == "textColor")
+ {
+ theTextColor = childNodes[idx]->getText();
+ theTextColor = theTextColor.trim();
+ }
+ else if(tag == "text")
+ {
+ theText = childNodes[idx]->getText();
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlBalloonStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+
+ xmlNode->setTag("BalloonStyle");
+ xmlNode->addChildNode("bgColor", theBackgroundColor);
+ xmlNode->addChildNode("textColor", theTextColor);
+ xmlNode->addChildNode("text", theText);
+}
+
+bool ossimPlanetKmlLod::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+
+ ossim_uint32 idx;
+ ossim_uint32 upper=childNodes.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+
+ if(tag == "minLodPixels")
+ {
+ theMinLodPixels = childNodes[idx]->getText().toInt32();
+ }
+ else if(tag == "maxLodPixels")
+ {
+ theMaxLodPixels = childNodes[idx]->getText().toInt32();
+ }
+ else if(tag == "minFadeExtent")
+ {
+ theMinFadeExtent = childNodes[idx]->getText().toInt32();
+ }
+ else if(tag == "maxFadeExtent")
+ {
+ theMaxFadeExtent = childNodes[idx]->getText().toInt32();
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlLod::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ xmlNode->setTag("Lod");
+
+ xmlNode->addChildNode("minLodPixels", ossimString::toString(theMinLodPixels));
+ xmlNode->addChildNode("maxLodPixels", ossimString::toString(theMaxLodPixels));
+ xmlNode->addChildNode("minFadeExtent", ossimString::toString(theMinFadeExtent));
+ xmlNode->addChildNode("maxFadeExtent", ossimString::toString(theMaxFadeExtent));
+
+ ossimPlanetKmlObject::write(xmlNode);
+}
+
+bool ossimPlanetKmlScale::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+
+ for(idx = 0; idx< upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "x")
+ {
+ theX = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "y")
+ {
+ theY = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "z")
+ {
+ theZ = childNodes[idx]->getText().toDouble();
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlScale::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ xmlNode->setTag("Scale");
+
+ xmlNode->addChildNode("x", ossimString::toString(theX));
+ xmlNode->addChildNode("y", ossimString::toString(theY));
+ xmlNode->addChildNode("z", ossimString::toString(theZ));
+
+ ossimPlanetKmlObject::write(xmlNode);
+}
+
+bool ossimPlanetKmlLocation::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+
+ for(idx = 0; idx< upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "longitude")
+ {
+ theLongitude = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "latitude")
+ {
+ theLatitude = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "altitude")
+ {
+ theAltitude = childNodes[idx]->getText().toDouble();
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlLocation::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ xmlNode->setTag("Location");
+
+ xmlNode->addChildNode("longitude",ossimString::toString(theLongitude));
+ xmlNode->addChildNode("latitude", ossimString::toString(theLatitude));
+ xmlNode->addChildNode("altitude", ossimString::toString(theAltitude));
+
+ ossimPlanetKmlObject::write(xmlNode);
+}
+
+bool ossimPlanetKmlOrientation::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+
+ for(idx = 0; idx< upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "heading")
+ {
+ theHeading = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "tilt")
+ {
+ thePitch = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "roll")
+ {
+ theRoll = childNodes[idx]->getText().toDouble();
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlOrientation::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ xmlNode->setTag("Orientation");
+ xmlNode->addChildNode("heading", ossimString::toString(theHeading));
+ xmlNode->addChildNode("tilt", ossimString::toString(thePitch));
+ xmlNode->addChildNode("roll", ossimString::toString(theRoll));
+}
+
+bool ossimPlanetKmlLatLonBox::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempText;
+ if(!xmlNode->getChildTextValue(tempText, "north"))
+ {
+ return false;
+ }
+ theNorth = tempText.toDouble();
+ if(!xmlNode->getChildTextValue(tempText, "south"))
+ {
+ return false;
+ }
+ theSouth = tempText.toDouble();
+ if(!xmlNode->getChildTextValue(tempText, "east"))
+ {
+ return false;
+ }
+ theEast = tempText.toDouble();
+ if(!xmlNode->getChildTextValue(tempText, "west"))
+ {
+ return false;
+ }
+ theWest = tempText.toDouble();
+
+ if(xmlNode->getChildTextValue(tempText, "rotation"))
+ {
+ theRotation = tempText.toDouble();
+ }
+ return true;
+}
+void ossimPlanetKmlLatLonBox::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ xmlNode->setTag("LatLonBox");
+ xmlNode->addChildNode("north", ossimString::toString(theNorth));
+ xmlNode->addChildNode("south", ossimString::toString(theSouth));
+ xmlNode->addChildNode("east", ossimString::toString(theEast));
+ xmlNode->addChildNode("west", ossimString::toString(theWest));
+ xmlNode->addChildNode("rotation", ossimString::toString(theRotation));
+}
+
+bool ossimPlanetKmlLatLonAltBox::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlLatLonBox::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempText;
+ if(xmlNode->getChildTextValue(tempText, "minAltitude"))
+ {
+ theMinAltitude = tempText.toDouble();
+ }
+ if(xmlNode->getChildTextValue(tempText, "maxAltitude"))
+ {
+ theMaxAltitude = tempText.toDouble();
+ }
+ ossimString altMode;
+ xmlNode->getChildTextValue(altMode, "altitudeMode");
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(altMode);
+
+ return true;
+}
+
+void ossimPlanetKmlLatLonAltBox::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlLatLonBox::write(xmlNode);
+ xmlNode->setTag("LatLonAltBox");
+ xmlNode->addChildNode("minAltitude", ossimString::toString(theMinAltitude));
+ xmlNode->addChildNode("maxAltitude", ossimString::toString(theMaxAltitude));
+ xmlNode->addChildNode("altitudeMode", ossimPlanetKmlConvertAltitudeMode(theAltitudeMode));
+}
+
+bool ossimPlanetKmlColorStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+
+ ossim_uint32 idx;
+ ossim_uint32 upper = childNodes.size();;
+ ossim_uint32 count = 0;
+ for(idx = 0; ((idx < upper)&&(count < 2)); ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "color")
+ {
+ theColor = childNodes[idx]->getText();
+ ++count;
+ }
+ else if(tag == "colorMode")
+ {
+ theColorMode = ossimPlanetKmlConvertColorMode(childNodes[idx]->getText());
+ ++count;
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlColorStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+ xmlNode->setTag("ColorStyle");
+ xmlNode->addChildNode("color", theColor);
+ xmlNode->addChildNode("colorMode", ossimPlanetKmlConvertColorMode(theColorMode));
+}
+
+bool ossimPlanetKmlLineStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ if(!ossimPlanetKmlColorStyle::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempString;
+
+ if(xmlNode->getChildTextValue(tempString, "width"))
+ {
+ theWidth = tempString.toFloat32();
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlLineStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlColorStyle::write(xmlNode);
+ xmlNode->setTag("LineStyle");
+ xmlNode->addChildNode("width", ossimString::toString(theWidth));
+}
+
+bool ossimPlanetKmlPolyStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ if(!ossimPlanetKmlColorStyle::parse(xmlNode))
+ {
+ return false;
+ }
+
+ ossimString tempString;
+
+ if(xmlNode->getChildTextValue(tempString, "fill"))
+ {
+ theFillFlag = tempString.toBool();
+ }
+
+ if(xmlNode->getChildTextValue(tempString, "outline"))
+ {
+ theOutlineFlag = tempString.toBool();
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlPolyStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlColorStyle::write(xmlNode);
+ xmlNode->setTag("PolyStyle");
+ xmlNode->addChildNode("fill", theFillFlag?"1":"0");
+ xmlNode->addChildNode("outline", theOutlineFlag?"1":"0");
+}
+
+bool ossimPlanetKmlIconStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlColorStyle::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+ ossim_uint32 count = 0;
+ for(idx = 0; ((idx< upper)&&(count < 4)); ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+
+ if(tag == "scale")
+ {
+ theScale = childNodes[idx]->getText().toDouble();
+ ++count;
+ }
+ else if(tag == "heading")
+ {
+ theHeading = childNodes[idx]->getText().toDouble();
+ ++count;
+ }
+ else if(tag == "Icon")
+ {
+ theIcon = new ossimPlanetKmlIcon;
+ theIcon->setParent(this);
+ if(!theIcon->parse(childNodes[idx]))
+ {
+ theIcon = 0;
+ return false;
+ }
+ ++count;
+ }
+ else if(tag == "hotSpot")
+ {
+ ossimString tempString;
+ if(childNodes[idx]->getAttributeValue(tempString, "x"))
+ {
+ theXHotspot = tempString.toFloat32();
+ }
+ if(childNodes[idx]->getAttributeValue(tempString, "y"))
+ {
+ theYHotspot = tempString.toFloat32();
+ }
+ if(childNodes[idx]->getAttributeValue(tempString, "xunits"))
+ {
+ theXUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ if(childNodes[idx]->getAttributeValue(tempString, "yunits"))
+ {
+ theYUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+
+ ++count;
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlIconStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlColorStyle::write(xmlNode);
+ xmlNode->setTag("IconStyle");
+ xmlNode->addChildNode("scale", ossimString::toString(theScale));
+ xmlNode->addChildNode("heading", ossimString::toString(theHeading));
+ if(theIcon.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theIcon->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ node->setTag("hotSpot");
+ node->addAttribute("x", ossimString::toString(theXHotspot));
+ node->addAttribute("y", ossimString::toString(theYHotspot));
+ node->addAttribute("xunits", ossimPlanetKmlConvertUnits(theXUnits));
+ node->addAttribute("yunits", ossimPlanetKmlConvertUnits(theYUnits));
+}
+
+bool ossimPlanetKmlLabelStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+
+ if(!ossimPlanetKmlColorStyle::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempText;
+ if(xmlNode->getChildTextValue(tempText, "scale"))
+ {
+ theScale = tempText.toDouble();
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlLabelStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlColorStyle::write(xmlNode);
+ xmlNode->setTag("LabelStyle");
+ xmlNode->addChildNode("scale", ossimString::toString(theScale));
+}
+
+bool ossimPlanetKmlStyle::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlStyleSelector::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "LineStyle")
+ {
+ theLineStyle = new ossimPlanetKmlLineStyle;
+ theLineStyle->setParent(this);
+ if(!theLineStyle->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "IconStyle")
+ {
+ theIconStyle = new ossimPlanetKmlIconStyle;
+ theIconStyle->setParent(this);
+ if(!theIconStyle->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "LabelStyle")
+ {
+ theLabelStyle = new ossimPlanetKmlLabelStyle;
+ theLabelStyle->setParent(this);
+ if(!theLabelStyle->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "PolyStyle")
+ {
+ thePolyStyle = new ossimPlanetKmlPolyStyle;
+ thePolyStyle->setParent(this);
+ if(!thePolyStyle->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "BalloonStyle")
+ {
+ theBalloonStyle = new ossimPlanetKmlBalloonStyle;
+ theBalloonStyle->setParent(this);
+ if(!theBalloonStyle->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlStyle::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlStyleSelector::write(xmlNode);
+ xmlNode->setTag("Style");
+ if(theIconStyle.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theIconStyle->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+ if(theLabelStyle.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theLabelStyle->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+ if(theLineStyle.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theLineStyle->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+ if(thePolyStyle.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ thePolyStyle->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+ if(theBalloonStyle.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theBalloonStyle->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+bool ossimPlanetKmlStyleMap::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlStyleSelector::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+
+ if(tag == "Pair")
+ {
+ ossimString key;
+ ossimString value;
+ if( childNodes[idx]->getChildTextValue(key, "key")&&
+ childNodes[idx]->getChildTextValue(value, "styleUrl"))
+ {
+// if(key == "normal")
+// {
+// theNormalUrl = value;
+// }
+// else if(key == "highlight")
+// {
+// theHighlightUrl = value;
+// }
+ theStyleMap.insert(std::make_pair(key.c_str(), value.c_str()));
+ }
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlStyleMap::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlStyleSelector::write(xmlNode);
+ xmlNode->setTag("StyleMap");
+ MapType::const_iterator i = theStyleMap.begin();
+ while(i != theStyleMap.end())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+
+ node->setTag("Pair");
+ node->addChildNode(ossimString(i->first), ossimString(i->second));
+ xmlNode->addChildNode(node.get());
+
+ ++i;
+ }
+}
+
+bool ossimPlanetKmlLink::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempText;
+
+ xmlNode->getChildTextValue(theHref, "href");
+ xmlNode->getChildTextValue(tempText, "refreshMode");
+ theRefreshMode = ossimPlanetKmlConvertRefreshMode(tempText);
+
+ xmlNode->getChildTextValue(tempText, "viewRefreshMode");
+ theViewRefreshMode = ossimPlanetKmlConvertViewRefreshMode(tempText);
+ xmlNode->getChildTextValue(theViewFormat, "viewFormat");
+ xmlNode->getChildTextValue(theHttpQuery, "httpQuery");
+ if(xmlNode->getChildTextValue(tempText, "refreshInterval"))
+ {
+ theRefreshInterval = tempText.toDouble();
+ }
+ if(xmlNode->getChildTextValue(tempText, "viewRefreshTime"))
+ {
+ theViewRefreshTime = tempText.toDouble();
+ }
+ if(xmlNode->getChildTextValue(tempText, "viewBoundScale"))
+ {
+ theViewBoundScale = tempText.toDouble();
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlLink::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+ xmlNode->setTag("Link");
+ xmlNode->addChildNode("href", theHref);
+ xmlNode->addChildNode("refreshMode", ossimPlanetKmlConvertRefreshMode(theRefreshMode));
+ xmlNode->addChildNode("viewRefreshMode", ossimPlanetKmlConvertViewRefreshMode(theViewRefreshMode));
+ xmlNode->addChildNode("viewFormat", theViewFormat);
+ xmlNode->addChildNode("httpQuery", theHttpQuery);
+ xmlNode->addChildNode("refreshInterval", ossimString::toString(theRefreshInterval));
+ xmlNode->addChildNode("viewRefreshTime", ossimString::toString(theViewRefreshTime));
+ xmlNode->addChildNode("viewBoundScale", ossimString::toString(theViewBoundScale));
+
+}
+
+ossimFilename ossimPlanetKmlLink::download(bool forceOverwrite,
+ const ossimFilename& locationOverride)const
+{
+ ossimFilename fileToLoad = theHref;
+
+ if(ossimFilename(fileToLoad).downcase().contains("http"))
+ {
+ if(locationOverride == "")
+ {
+ fileToLoad = getCacheLocation(true); // will use the root kml to find the cache location
+ if(fileToLoad == "")
+ {
+ return "";
+ }
+// ossimFilename temp(ossimString(wmsUrl(theHref).path()).after("/"));
+ ossimFilename temp(wmsUrl(theHref.string()).server());
+ temp = ossimFilename(temp.substitute(".", "_", true));
+ temp = temp.dirCat(ossimFilename(wmsUrl(theHref.string()).path()));
+ fileToLoad = fileToLoad.dirCat(temp);
+ ossimFilename path = fileToLoad.path();
+ path.createDirectory();
+ }
+ else
+ {
+ fileToLoad = locationOverride;
+ }
+
+ if((!fileToLoad.exists())||
+ (forceOverwrite))
+ {
+ ossimFilename tempFile = ossimFilename(fileToLoad + ".tmp");
+ wmsCurlMemoryStream netDownload(theHref);
+
+ if(!netDownload.download(tempFile))
+ {
+ return "";
+ }
+ tempFile.rename(fileToLoad, true);
+
+ }
+ }
+ else if(!fileToLoad.exists())// check absolute and relative
+ {
+ ossimFilename file = getKmlFile();
+ if(!file.empty())
+ {
+ ossimFilename testFile = file.path().dirCat(fileToLoad);
+ if(testFile.exists())
+ {
+ fileToLoad = testFile;
+ }
+ }
+ }
+ // really need to check other protocols. Maybe need to check for file:// and convert to
+ // local file
+ //
+
+ return fileToLoad;
+}
+
+bool ossimPlanetKmlIcon::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ return ossimPlanetKmlLink::parse(xmlNode);
+}
+
+void ossimPlanetKmlIcon::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlLink::write(xmlNode);
+ xmlNode->setTag("Icon");
+}
+
+bool ossimPlanetKmlRegion::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid()) return false;
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+
+ if(tag == "Lod")
+ {
+ theLod = new ossimPlanetKmlLod;
+ theLod->setParent(this);
+ if(!theLod->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "LatLonAltBox")
+ {
+ theBox = new ossimPlanetKmlLatLonAltBox;
+ theBox->setParent(this);
+ if(!theBox->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ }
+
+ return theBox.valid();
+}
+
+
+void ossimPlanetKmlRegion::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+
+ xmlNode->setTag("Region");
+ if(theLod.valid())
+ {
+ ossimRefPtr<ossimXmlNode> lodNode = new ossimXmlNode;
+ theLod->write(lodNode.get());
+ xmlNode->addChildNode(lodNode.get());
+ }
+ if(theBox.valid())
+ {
+ ossimRefPtr<ossimXmlNode> boxNode = new ossimXmlNode;
+ theBox->write(boxNode.get());
+ xmlNode->addChildNode(boxNode.get());
+ }
+}
+
+bool ossimPlanetKmlLookAt::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempText;
+ if(!xmlNode->getChildTextValue(tempText, "longitude"))
+ {
+ return false;
+ }
+ theLookAt->setLon(tempText.toDouble());
+ if(!xmlNode->getChildTextValue(tempText, "latitude"))
+ {
+ return false;
+ }
+ theLookAt->setLat(tempText.toDouble());
+ if(!xmlNode->getChildTextValue(tempText, "range"))
+ {
+ return false;
+ }
+ theLookAt->setRange(tempText.toDouble());
+
+ if(xmlNode->getChildTextValue(tempText, "altitude"))
+ {
+ theLookAt->setAltitude(tempText.toDouble());
+ }
+
+ if(xmlNode->getChildTextValue(tempText, "tilt"))
+ {
+ theLookAt->setPitch(tempText.toDouble());
+ theLookAt->setPitch(mkUtils::clamp(theLookAt->pitch(), (double)0.0, (double)90.0));
+ }
+
+ if(xmlNode->getChildTextValue(tempText, "heading"))
+ {
+ theLookAt->setHeading(tempText.toDouble());
+ }
+ if(xmlNode->getChildTextValue(tempText, "altitudeMode"))
+ {
+ theLookAt->setAltitudeMode(ossimPlanetLookAt::modeFromString(tempText));
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlLookAt::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+ xmlNode->setTag("LookAt");
+
+ xmlNode->addChildNode("longitude", ossimString::toString(theLookAt->lon()));
+ xmlNode->addChildNode("latitude", ossimString::toString(theLookAt->lat()));
+ xmlNode->addChildNode("range", ossimString::toString(theLookAt->range()));
+ xmlNode->addChildNode("altitude", ossimString::toString(theLookAt->altitude()));
+ xmlNode->addChildNode("tilt", ossimString::toString(theLookAt->pitch()));
+ xmlNode->addChildNode("heading", ossimString::toString(theLookAt->heading()));
+ xmlNode->addChildNode("altitudeMode", ossimPlanetLookAt::modeToString(theLookAt->altitudeMode()));
+}
+
+bool ossimPlanetKmlTimeSpan::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+
+ xmlNode->getChildTextValue(theBegin, "begin");
+ xmlNode->getChildTextValue(theEnd, "end");
+
+ return true;
+}
+
+void ossimPlanetKmlTimeSpan::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlTimePrimitive::write(xmlNode);
+ xmlNode->setTag("TimeSpan");
+
+ if(!theBegin.empty())
+ {
+ xmlNode->addChildNode("begin", theBegin);
+ }
+ if(!theEnd.empty())
+ {
+ xmlNode->addChildNode("end", theEnd);
+ }
+}
+
+bool ossimPlanetKmlTimeStamp::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+
+ xmlNode->getChildTextValue(theWhen, "when");
+
+ return true;
+}
+
+void ossimPlanetKmlTimeStamp::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ xmlNode->setTag("TimeStamp");
+ ossimPlanetKmlTimePrimitive::write(xmlNode);
+ xmlNode->addChildNode("when", theWhen);
+}
+
+bool ossimPlanetKmlFeature::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!xmlNode.valid()) return false;
+ if(!ossimPlanetKmlObject::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ ossimString tempString;
+
+ if(tag == "name")
+ {
+ theName = childNodes[idx]->getText();
+ }
+ else if(tag == "visibility")
+ {
+ theVisibilityFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "open")
+ {
+ theOpenFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "address")
+ {
+ theAddress = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "phoneNumber")
+ {
+ theAddress = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "Region")
+ {
+ theRegion = new ossimPlanetKmlRegion();
+ theRegion->setParent(this);
+ if(!theRegion->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "description")
+ {
+ theDescription = childNodes[idx]->getText();
+ theCDataDescriptionFlag = childNodes[idx]->cdataFlag();
+ if(!theCDataDescriptionFlag)
+ {
+ theDescription = ossim::convertHtmlSpecialCharactersToNormalCharacter(theDescription);
+ }
+ }
+ else if(tag == "LookAt")
+ {
+ theLookAt = new ossimPlanetKmlLookAt();
+ theLookAt->setParent(this);
+ if(!theLookAt->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "styleUrl")
+ {
+ theStyleUrl = childNodes[idx]->getText();
+ }
+ else if(tag == "Snippet")
+ {
+ theSnippet = childNodes[idx]->getText();
+ childNodes[idx]->getAttributeValue(theSnippetMaxLines, "maxLines");
+ }
+ else if(tag == "Metadata")
+ {
+ theExtendedData = childNodes[idx];
+ }
+ else if(tag == "ExtendedData")
+ {
+ theExtendedData = childNodes[idx];
+ }
+ else if(tag == "Style")
+ {
+ theStyleSelector = new ossimPlanetKmlStyle;
+ theStyleSelector->setParent(this);
+ if(!theStyleSelector->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "StyleMap")
+ {
+ theStyleSelector = new ossimPlanetKmlStyleMap;
+ theStyleSelector->setParent(this);
+ if(!theStyleSelector->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ossimPlanetKmlObject* timePrimitive = ossimPlanetKmlObjectRegistry::instance()->newTimePrimitive(tag);
+ if(timePrimitive)
+ {
+ theTimePrimitive = (ossimPlanetKmlTimePrimitive*)timePrimitive;
+ theTimePrimitive->setParent(this);
+ }
+ }
+ }
+ return true;
+}
+
+void ossimPlanetKmlFeature::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+
+ xmlNode->addChildNode("name", name());
+ xmlNode->addChildNode("visibility", visibilityFlag()?"1":"0");
+ xmlNode->addChildNode("open", openFlag()?"1":"0");
+ xmlNode->addChildNode("address", address());
+ xmlNode->addChildNode("phoneNumber", phoneNumber());
+ if(theCDataDescriptionFlag)
+ {
+ ossimRefPtr<ossimXmlNode> xmlTempNode = new ossimXmlNode;
+ xmlNode->setTag("description");
+ xmlNode->setCDataFlag(true);
+ xmlNode->setText(description());
+ }
+ else
+ {
+ xmlNode->addChildNode("description", description());
+ }
+ xmlNode->addChildNode("styleUrl", styleUrl());
+ if(theRegion.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theRegion->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ if(theLookAt.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theLookAt->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ if(!theSnippet.empty())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ node->setTag("Snippet");
+ if(!theSnippetMaxLines.empty())
+ {
+ node->addAttribute("maxLines", theSnippetMaxLines);
+ }
+ xmlNode->addChildNode(node.get());
+
+ }
+ if(theExtendedData.valid())
+ {
+ xmlNode->addChildNode((ossimXmlNode*)theExtendedData->dup());
+ }
+ if(theStyleSelector.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theStyleSelector->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ if(theTimePrimitive.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theTimePrimitive->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+bool ossimPlanetKmlGeometry::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ return ossimPlanetKmlObject::parse(xmlNode);
+}
+
+void ossimPlanetKmlGeometry::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlObject::write(xmlNode);
+}
+
+void ossimPlanetKmlGeometry::computeCenter(osg::Vec3d& result,
+ const PointListType& pointList)
+{
+ ossim_uint32 idx;
+ double minLat=999999.0, minLon=999999.0;
+ double maxLat=-999999.0, maxLon=-999999.0;
+ double minAlt=99999999.0, maxAlt=-99999999.0;
+
+ if(pointList.size())
+ {
+ for(idx = 0; idx < pointList.size(); ++idx)
+ {
+ osg::Vec3d pt = pointList[idx];
+ if(pt[0]<minLon) minLon = pt[0];
+ if(pt[0]>maxLon) maxLon = pt[0];
+ if(pt[1]<minLat) minLat = pt[1];
+ if(pt[1]>maxLat) maxLat = pt[1];
+ if(pt[2]<minAlt) minAlt = pt[2];
+ if(pt[2]>maxAlt) maxAlt = pt[2];
+ }
+ result[0] = (maxLon+minLon)*.5;
+ result[1] = (maxLat+minLat)*.5;
+ result[2] = (maxAlt+minAlt)*.5;
+ if(maxLon-minLon > 180.0) // we will guess it crossed the -180 mark.
+ {
+ double len1, len2, totalLen;
+ len1 = 180-maxLon;
+ len2 = 180+minLon;
+ totalLen = len1+len2;
+ result[0] += maxLon + totalLen*.5;
+ if(result[0] > 180) result[0] -= 360.0;
+ }
+ }
+}
+
+bool ossimPlanetKmlPoint::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!ossimPlanetKmlGeometry::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ bool hasCoordinates = true;
+ for(idx = 0; idx < childNodes.size(); ++idx)
+ {
+ if(childNodes[idx]->getTag() == "extrude")
+ {
+ theExtrudeFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "tessellate")
+ {
+ theTesselateFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "altitudeMode")
+ {
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(childNodes[idx]->getText());
+ }
+ else if(childNodes[idx]->getTag() == "coordinates")
+ {
+ kmlReadCoordinates(thePointList, childNodes[idx]->getText());
+ computeCenter(theCenter, thePointList);
+ }
+ }
+ return hasCoordinates;
+}
+
+void ossimPlanetKmlPoint::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlGeometry::write(xmlNode);
+ xmlNode->setTag("Point");
+
+ xmlNode->addChildNode("extrude", theExtrudeFlag?"1":"0");
+ xmlNode->addChildNode("tessellate", theTesselateFlag?"1":"0");
+ xmlNode->addChildNode("altitudeMode", ossimPlanetKmlConvertAltitudeMode(theAltitudeMode));
+
+ if(thePointList.size() > 0)
+ {
+ ossimString value = ossimString::toString(thePointList[0][0]) + "," +
+ ossimString::toString(thePointList[0][1]) + "," +
+ ossimString::toString(thePointList[0][2]);
+
+ xmlNode->addChildNode("coordinates", value);
+ }
+}
+
+bool ossimPlanetKmlLineString::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!ossimPlanetKmlGeometry::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempString;
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ bool hasCoordinates = false;
+ for(idx = 0; idx < childNodes.size(); ++idx)
+ {
+ if(childNodes[idx]->getTag() == "extrude")
+ {
+ theExtrudeFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "tessellate")
+ {
+ theTesselateFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "altitudeMode")
+ {
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(childNodes[idx]->getText());
+ }
+ else if(childNodes[idx]->getTag() == "coordinates")
+ {
+ hasCoordinates = true;
+ kmlReadCoordinates(thePointList, childNodes[idx]->getText());
+ computeCenter(theCenter, thePointList);
+ }
+ }
+ return hasCoordinates;
+}
+
+void ossimPlanetKmlLineString::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlGeometry::write(xmlNode);
+ xmlNode->setTag("LineString");
+ xmlNode->addChildNode("extrude", theExtrudeFlag?"1":"0");
+ xmlNode->addChildNode("tessellate", theTesselateFlag?"1":"0");
+ xmlNode->addChildNode("altitudeMode", ossimPlanetKmlConvertAltitudeMode(theAltitudeMode));
+ ossimString value;
+ if(thePointList.size() > 0)
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < thePointList.size(); ++idx)
+ {
+ value += (ossimString::toString(thePointList[idx][0])+","+
+ ossimString::toString(thePointList[idx][1])+","+
+ ossimString::toString(thePointList[idx][2])+" ");
+ }
+ }
+ xmlNode->addChildNode("coordinates", value);
+}
+
+bool ossimPlanetKmlLinearRing::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!ossimPlanetKmlGeometry::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempString;
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ bool hasCoordinates = false;
+ for(idx = 0; idx < childNodes.size(); ++idx)
+ {
+ if(childNodes[idx]->getTag() == "extrude")
+ {
+ theExtrudeFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "tessellate")
+ {
+ theTesselateFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "altitudeMode")
+ {
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(childNodes[idx]->getText());
+ }
+ else if(childNodes[idx]->getTag() == "coordinates")
+ {
+ hasCoordinates = true;
+ kmlReadCoordinates(thePointList, childNodes[idx]->getText());
+ computeCenter(theCenter, thePointList);
+ }
+ }
+ return hasCoordinates;
+}
+
+void ossimPlanetKmlLinearRing::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlGeometry::write(xmlNode);
+ xmlNode->setTag("LinearRing");
+ xmlNode->addChildNode("extrude", theExtrudeFlag?"1":"0");
+ xmlNode->addChildNode("tessellate", theTesselateFlag?"1":"0");
+ xmlNode->addChildNode("altitudeMode", ossimPlanetKmlConvertAltitudeMode(theAltitudeMode));
+ ossimString value;
+ if(thePointList.size() > 0)
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < thePointList.size()-1; ++idx)
+ {
+ value += (ossimString::toString(thePointList[idx][0])+","+
+ ossimString::toString(thePointList[idx][1])+","+
+ ossimString::toString(thePointList[idx][2])+" ");
+ }
+ }
+ xmlNode->addChildNode("coordinates", value);
+}
+
+bool ossimPlanetKmlPolygon::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!ossimPlanetKmlGeometry::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = childNodes.size();
+
+ for(idx = 0; idx < bound; ++idx)
+ {
+ if(childNodes[idx]->getTag() == "extrude")
+ {
+ theExtrudeFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "tessellate")
+ {
+ theTesselateFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(childNodes[idx]->getTag() == "altitudeMode")
+ {
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(childNodes[idx]->getText());
+ }
+ else if(childNodes[idx]->getTag() == "outerBoundaryIs")
+ {
+ theOuterBoundary = new ossimPlanetKmlLinearRing;
+ theOuterBoundary->parse(childNodes[idx]->findFirstNode("LinearRing"));
+ theOuterBoundary->setParent(this);
+ }
+ else if(childNodes[idx]->getTag() == "innerBoundaryIs")
+ {
+ ossimPlanetKmlLinearRing* linearRing = new ossimPlanetKmlLinearRing;
+ if(linearRing->parse(childNodes[idx]->findFirstNode("LinearRing")))
+ {
+ linearRing->setParent(this);
+ theInnerBoundaryList.push_back(linearRing);
+ }
+ }
+ }
+ return theOuterBoundary.valid();
+}
+
+void ossimPlanetKmlPolygon::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlGeometry::write(xmlNode);
+
+ xmlNode->setTag("Polygon");
+
+ xmlNode->addChildNode("extrude", theExtrudeFlag?"1":"0");
+ xmlNode->addChildNode("tessellate", theTesselateFlag?"1":"0");
+ xmlNode->addChildNode("altitudeMode", ossimPlanetKmlConvertAltitudeMode(theAltitudeMode));
+ if(theOuterBoundary.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ ossimRefPtr<ossimXmlNode> linearRingNode = new ossimXmlNode;
+ theOuterBoundary->write(linearRingNode);
+ node->addChildNode(linearRingNode.get());
+ node->setTag("outerBoundaryIs");
+ xmlNode->addChildNode(node.get());
+ }
+ if(!theInnerBoundaryList.empty())
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theInnerBoundaryList.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ ossimRefPtr<ossimXmlNode> linearRingNode = new ossimXmlNode;
+ theInnerBoundaryList[idx]->write(linearRingNode);
+ node->addChildNode(linearRingNode.get());
+ node->setTag("innerBoundaryIs");
+ xmlNode->addChildNode(node.get());
+ }
+ }
+}
+
+bool ossimPlanetKmlMultiGeometry::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!ossimPlanetKmlGeometry::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = childNodes.size();
+
+ for(idx = 0; idx < bound; ++idx)
+ {
+ osg::ref_ptr<ossimPlanetKmlGeometry> geom = (ossimPlanetKmlGeometry*)ossimPlanetKmlObjectRegistry::instance()->newGeometry(childNodes[idx]->getTag());
+ if(geom.valid())
+ {
+ if(geom->parse(childNodes[idx]))
+ {
+ theGeometryList.push_back(geom.get());
+ geom->setParent(this);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+
+}
+
+void ossimPlanetKmlMultiGeometry::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlGeometry::write(xmlNode);
+
+ xmlNode->setTag("MultiGeometry");
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theGeometryList.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theGeometryList[idx]->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+bool ossimPlanetKmlModel::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!xmlNode.valid())
+ {
+ return false;
+ }
+ if(!ossimPlanetKmlGeometry::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = childNodes.size();
+ for(idx = 0; idx < bound; ++idx)
+ {
+ if(childNodes[idx]->getTag() == "Location")
+ {
+ if(!theLocation->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(childNodes[idx]->getTag() == "Orientation")
+ {
+ if(!theOrientation->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(childNodes[idx]->getTag() == "Scale")
+ {
+ if(!theScale->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(childNodes[idx]->getTag() == "Link")
+ {
+ theLink = new ossimPlanetKmlLink;
+ theLink->setParent(this);
+ if(!theLink->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(childNodes[idx]->getTag() == "altitudeMode")
+ {
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(childNodes[idx]->getText());
+ }
+ }
+
+ return true;
+
+}
+
+void ossimPlanetKmlModel::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlGeometry::write(xmlNode);
+ xmlNode->setTag("Model");
+ ossimRefPtr<ossimXmlNode> node;
+ if(theLocation.valid())
+ {
+ node = new ossimXmlNode;
+ theLocation->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ if(theOrientation.valid())
+ {
+ node = new ossimXmlNode;
+ theOrientation->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ if(theScale.valid())
+ {
+ node = new ossimXmlNode;
+ theScale->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+ if(theLink.valid())
+ {
+ node = new ossimXmlNode;
+ theLink->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+bool ossimPlanetKmlOverlay::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ ossimString tempString;
+ clearFields();
+
+ xmlNode->getChildTextValue(theColor, "color");
+ if(xmlNode->getChildTextValue(tempString, "drawOrder"))
+ {
+ theDrawOrder = tempString.toInt32();
+ }
+ const ossimRefPtr<ossimXmlNode> iconNode = xmlNode->findFirstNode("Icon");
+ if(iconNode.valid())
+ {
+ theIcon = new ossimPlanetKmlIcon();
+ theIcon->setParent(this);
+ if(!theIcon->parse(iconNode))
+ {
+ return false;
+ }
+ }
+ return ossimPlanetKmlFeature::parse(xmlNode);
+}
+
+void ossimPlanetKmlOverlay::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlFeature::write(xmlNode);
+ xmlNode->addChildNode("color", theColor);
+ xmlNode->addChildNode("drawOrder", ossimString::toString(theDrawOrder));
+
+ if(theIcon.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theIcon->write(node);
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+bool ossimPlanetKmlScreenOverlay::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ if(!ossimPlanetKmlOverlay::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimString tempString;
+ ossimRefPtr<ossimXmlNode> tempNode = xmlNode->findFirstNode("overlayXY");
+ if(tempNode.valid())
+ {
+ if(tempNode->getAttributeValue(tempString, "x"))
+ {
+ theOverlayX = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "y"))
+ {
+ theOverlayY = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "xunits"))
+ {
+ theOverlayXUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ if(tempNode->getAttributeValue(tempString, "yunits"))
+ {
+ theOverlayYUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ }
+ tempNode = xmlNode->findFirstNode("screenXY");
+ if(tempNode.valid())
+ {
+ if(tempNode->getAttributeValue(tempString, "x"))
+ {
+ theScreenX = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "y"))
+ {
+ theScreenY = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "xunits"))
+ {
+ theScreenXUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ if(tempNode->getAttributeValue(tempString, "yunits"))
+ {
+ theScreenYUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ }
+ tempNode = xmlNode->findFirstNode("rotationXY");
+ if(tempNode.valid())
+ {
+ if(tempNode->getAttributeValue(tempString, "x"))
+ {
+ theRotationX = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "y"))
+ {
+ theRotationY = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "xunits"))
+ {
+ theRotationXUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ if(tempNode->getAttributeValue(tempString, "yunits"))
+ {
+ theRotationYUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ }
+ tempNode = xmlNode->findFirstNode("size");
+ if(tempNode.valid())
+ {
+ if(tempNode->getAttributeValue(tempString, "x"))
+ {
+ theSizeX = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "y"))
+ {
+ theSizeY = tempString.toDouble();
+ }
+ if(tempNode->getAttributeValue(tempString, "xunits"))
+ {
+ theSizeXUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ if(tempNode->getAttributeValue(tempString, "yunits"))
+ {
+ theSizeYUnits = ossimPlanetKmlConvertUnits(tempString);
+ }
+ }
+ tempNode = xmlNode->findFirstNode("rotation");
+ if(tempNode.valid())
+ {
+ theRotation = tempNode->getText().toDouble();
+ }
+
+ return true;
+}
+
+void ossimPlanetKmlScreenOverlay::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlOverlay::write(xmlNode);
+ xmlNode->setTag("ScreenOverlay");
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ node->setTag("overlayXY");
+ node->addAttribute("x", ossimString::toString(theOverlayX));
+ node->addAttribute("y", ossimString::toString(theOverlayY));
+ node->addAttribute("xunits", ossimPlanetKmlConvertUnits(theOverlayXUnits));
+ node->addAttribute("yunits", ossimPlanetKmlConvertUnits(theOverlayYUnits));
+ xmlNode->addChildNode(node.get());
+
+ node = new ossimXmlNode;
+ node->setTag("screenXY");
+ node->addAttribute("x", ossimString::toString(theScreenX));
+ node->addAttribute("y", ossimString::toString(theScreenY));
+ node->addAttribute("xunits", ossimPlanetKmlConvertUnits(theScreenXUnits));
+ node->addAttribute("yunits", ossimPlanetKmlConvertUnits(theScreenYUnits));
+ xmlNode->addChildNode(node.get());
+
+ node = new ossimXmlNode;
+ node->setTag("rotationXY");
+ node->addAttribute("x", ossimString::toString(theRotationX));
+ node->addAttribute("y", ossimString::toString(theRotationY));
+ node->addAttribute("xunits", ossimPlanetKmlConvertUnits(theRotationXUnits));
+ node->addAttribute("yunits", ossimPlanetKmlConvertUnits(theRotationYUnits));
+ xmlNode->addChildNode(node.get());
+
+ node = new ossimXmlNode;
+ xmlNode->setTag("size");
+ node->addAttribute("x", ossimString::toString(theSizeX));
+ node->addAttribute("y", ossimString::toString(theSizeY));
+ node->addAttribute("xunits", ossimPlanetKmlConvertUnits(theSizeXUnits));
+ node->addAttribute("yunits", ossimPlanetKmlConvertUnits(theSizeYUnits));
+ xmlNode->addChildNode(node.get());
+
+ xmlNode->addChildNode("rotation", ossimString::toString(theRotation));
+}
+
+bool ossimPlanetKmlGroundOverlay::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlOverlay::parse(xmlNode))
+ {
+ return false;
+ }
+ ossimRefPtr<ossimXmlNode> latLonBoxNode = xmlNode->findFirstNode("LatLonBox");
+ if(!latLonBoxNode.valid())
+ {
+ return false;
+ }
+ theLatLonBox = new ossimPlanetKmlLatLonBox();
+ theLatLonBox->setParent(this);
+ if(!theLatLonBox->parse(latLonBoxNode))
+ {
+ theLatLonBox = 0;
+ return false;
+ }
+ ossimString tempString;
+ if(xmlNode->getChildTextValue(tempString, "altitude"))
+ {
+ theAltitude = tempString.toDouble();
+ }
+ xmlNode->getChildTextValue(tempString, "altitudeMode");
+ theAltitudeMode = ossimPlanetKmlConvertAltitudeMode(tempString);
+
+ return true;
+}
+
+void ossimPlanetKmlGroundOverlay::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlOverlay::write(xmlNode);
+ xmlNode->setTag("GroundOverlay");
+ if(theLatLonBox.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theLatLonBox->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ xmlNode->addChildNode("altitude", ossimString::toString(theAltitude));
+ xmlNode->addChildNode("altitudeMode", ossimPlanetKmlConvertAltitudeMode(theAltitudeMode));
+}
+bool ossimPlanetKmlNetworkLink::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(!ossimPlanetKmlFeature::parse(xmlNode))
+ {
+ return false;
+ }
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < childNodes.size(); ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "flyToView")
+ {
+ theFlyToViewFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "refreshVisibility")
+ {
+ theRefreshVisibilityFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "Link")
+ {
+ theLink = new ossimPlanetKmlLink;
+ theLink->setParent(this);
+ if(!theLink->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ else if(tag == "Url")
+ {
+ theLink = new ossimPlanetKmlLink;
+ theLink->setParent(this);
+ if(!theLink->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ }
+ }
+
+
+ return theLink.valid();
+}
+
+void ossimPlanetKmlNetworkLink::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlFeature::write(xmlNode);
+ xmlNode->setTag("NetworkLink");
+ if(theLink.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theLink->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+ xmlNode->addChildNode("refreshVisibility", theRefreshVisibilityFlag?"1":"0");
+ xmlNode->addChildNode("flyToView", theFlyToViewFlag?"!":"0");
+}
+
+
+bool ossimPlanetKmlPlacemark::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ clearFields();
+ if(xmlNode->getTag() == "Placemark")
+ {
+ ossim_uint32 foundCount = 0;
+ ossim_uint32 idx = 0;
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ for(idx = 0; (idx < childNodes.size())&&(foundCount < 1); ++idx)
+ {
+ std::string tag = childNodes[idx]->getTag().c_str();
+ if(tag == "description")
+ {
+ theDescription = childNodes[idx]->getText();
+
+ /*
+ theCDataDescriptionFlag = childNodes[idx]->cdataFlag();
+ ossimRefPtr<ossimXmlNode> node2 = new ossimXmlNode;
+ std::istringstream in(theDescription);
+ if(node2->read(in))
+ {
+ }
+ */
+
+ if(theDescription.contains("<color>"))
+ {
+ ossimString temp = theDescription.after("<color>");
+ std::string color = temp.before("</color>").c_str();
+ //std::cout << "T:" << color << "\n";
+ this->setColor(color);
+ }
+ }
+ theGeometry = (ossimPlanetKmlGeometry*)ossimPlanetKmlObjectRegistry::instance()->newGeometry(childNodes[idx]->getTag());
+ if(theGeometry.valid())
+ {
+ theGeometry->setParent(this);
+ if(!theGeometry->parse(childNodes[idx]))
+ {
+ return false;
+ }
+ ++foundCount;
+ }
+ }
+
+ return ossimPlanetKmlFeature::parse(xmlNode);
+ }
+
+ return false;
+}
+
+void ossimPlanetKmlPlacemark::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlFeature::write(xmlNode);
+ xmlNode->setTag("Placemark");
+ if(theGeometry.valid())
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theGeometry->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+
+bool ossimPlanetKmlContainer::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ if(!xmlNode.valid()) return false;
+
+ bool result = ossimPlanetKmlFeature::parse(xmlNode);
+ if(result)
+ {
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; (idx < childNodes.size())&&result; ++idx)
+ {
+ osg::ref_ptr<ossimPlanetKmlObject> obj = ossimPlanetKmlObjectRegistry::instance()->newObject(childNodes[idx].get());
+ if(obj.valid())
+ {
+ obj->setParent(this);
+ if(obj->parse(childNodes[idx]))
+ {
+ theObjectList.push_back(obj.get());
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetKmlContainer::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlFeature::write(xmlNode);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theObjectList.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theObjectList[idx]->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+bool ossimPlanetKmlFolder::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ return ossimPlanetKmlContainer::parse(xmlNode);
+}
+
+void ossimPlanetKmlFolder::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlContainer::write(xmlNode);
+ xmlNode->setTag("Folder");
+}
+
+
+ossimPlanetKmlDocument::ossimPlanetKmlDocument()
+{
+}
+
+bool ossimPlanetKmlDocument::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ return ossimPlanetKmlContainer::parse(xmlNode);
+}
+
+void ossimPlanetKmlDocument::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossimPlanetKmlContainer::write(xmlNode);
+ xmlNode->setTag("Document");
+
+}
+
+ossimPlanetKml::ossimPlanetKml()
+ :theIdMapGeneratedFlag(false)
+{
+}
+
+bool ossimPlanetKml::parse(const ossimFilename& file)
+{
+ theIdMapGeneratedFlag = false;
+
+ std::vector<char> buf(file.fileSize());
+ if(!buf.size())
+ {
+ return false;
+ }
+ std::ifstream in(file.c_str(), std::ios::binary|std::ios::in);
+ in.read(&buf.front(), buf.size());
+
+ if(in.gcount())
+ {
+ std::istringstream inStringStream(std::string(buf.begin(),
+ buf.begin()+in.gcount()));
+ theFilename = file;
+
+ return parse(inStringStream);
+ }
+
+ return false;
+}
+
+bool ossimPlanetKml::parse(std::istream& in, bool fullDocumentFlag)
+{
+ bool result = false;
+ theIdMapGeneratedFlag = false;
+ if(!in.fail())
+ {
+ if(fullDocumentFlag)
+ {
+ ossimRefPtr<ossimXmlDocument> document = new ossimXmlDocument;
+
+ if(document->read(in))
+ {
+ result = parse(document.get());
+ }
+ }
+ else
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ if(node->read(in))
+ {
+ result = parse(node.get());
+ }
+ }
+ }
+
+ return result;
+}
+
+bool ossimPlanetKml::parse(const ossimRefPtr<ossimXmlDocument> document)
+{
+ bool result = document.valid();
+ theIdMapGeneratedFlag = false;
+
+ if(result)
+ {
+ if(document->getRoot().valid())
+ {
+ result = parse(document->getRoot());
+ }
+ else
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+bool ossimPlanetKml::parse(const ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ bool result = true;
+ if(!xmlNode.valid()) return false;
+ if(xmlNode->getTag() != "kml") return false;
+
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; (idx < childNodes.size())&&(result); ++idx)
+ {
+ osg::ref_ptr<ossimPlanetKmlObject> obj = ossimPlanetKmlObjectRegistry::instance()->newObject(childNodes[idx].get());
+ if(obj.valid())
+ {
+ obj->setParent(this);
+ result = obj->parse(childNodes[idx]);
+ if(result)
+ {
+ theObjectList.push_back(obj.get());
+ }
+ }
+ }
+
+// if(result)
+// {
+// ossimRefPtr<ossimXmlDocument> doc = writeDocument();
+// std::cout << *(doc.get()) << std::endl;
+// }
+ return result;
+}
+
+void ossimPlanetKml::write(ossimRefPtr<ossimXmlNode> xmlNode)const
+{
+ ossim_uint32 idx = 0;
+ xmlNode->setTag("Kml");
+ for(idx = 0; idx < theObjectList.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ theObjectList[idx]->write(node.get());
+ xmlNode->addChildNode(node.get());
+ }
+}
+
+ossimRefPtr<ossimXmlDocument> ossimPlanetKml::writeDocument()const
+{
+ ossimRefPtr<ossimXmlDocument> document = new ossimXmlDocument;
+ ossimRefPtr<ossimXmlNode> rootNode = new ossimXmlNode;
+ document->initRoot(rootNode);
+ write(rootNode);
+
+ return document;
+}
+
+void ossimPlanetKml::createIdMap()const
+{
+ theIdMap.clear();
+ std::queue<osg::ref_ptr<ossimPlanetKmlObject> > objectSearchQueue;
+ ossimPlanetKmlObject::ObjectList::const_iterator iter = theObjectList.begin();
+ while(iter != theObjectList.end())
+ {
+ objectSearchQueue.push(*iter);
+ ++iter;
+ }
+ while(!objectSearchQueue.empty())
+ {
+ osg::ref_ptr<ossimPlanetKmlObject> topObj = objectSearchQueue.front().get();
+ objectSearchQueue.pop();
+ if(topObj->id() != "")
+ {
+ theIdMap.insert(std::make_pair(topObj->id().c_str(), topObj));
+ }
+ if(topObj->getObjectList().size())
+ {
+ ossim_uint32 idx = 0;
+ ossimPlanetKmlObject::ObjectList& objList = topObj->getObjectList();
+
+ for(idx = 0; idx < objList.size(); ++idx)
+ {
+ objectSearchQueue.push(objList[idx]);
+ }
+ }
+ }
+ theIdMapGeneratedFlag = true;
+}
+
+osg::ref_ptr<ossimPlanetKmlObject> ossimPlanetKml::findById(const ossimString& id)
+{
+ if(!theIdMapGeneratedFlag)
+ {
+ createIdMap();
+ }
+ IdMapType::iterator iter = theIdMap.find(id);
+
+ if(iter != theIdMap.end())
+ {
+ return iter->second;
+ }
+
+ return 0;
+}
+
+const osg::ref_ptr<ossimPlanetKmlObject> ossimPlanetKml::findById(const ossimString& id)const
+{
+ if(!theIdMapGeneratedFlag)
+ {
+ createIdMap();
+ }
+
+ IdMapType::const_iterator iter = theIdMap.find(id);
+
+ if(iter != theIdMap.end())
+ {
+ return iter->second.get();
+ }
+
+ return 0;
+}
+
+ossimFilename ossimPlanetKml::getCacheLocation(bool sharedLocationFlag)const
+{
+ if(sharedLocationFlag)
+ {
+ ossimFilename sharedDir = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ sharedDir = sharedDir.dirCat("kml");
+ if(!sharedDir.exists())
+ {
+ sharedDir.createDirectory();
+ }
+ return sharedDir;
+ }
+ if(theCacheLocation == "")
+ {
+ theCacheLocation = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ theCacheLocation = theCacheLocation.dirCat("kml");
+ if(theCacheLocation != "")
+ {
+ theCacheLocation = theCacheLocation.dirCat(theFilename.fileNoExtension());
+ }
+ if(!theCacheLocation.exists())
+ {
+ theCacheLocation.createDirectory();
+ }
+ }
+
+ return theCacheLocation;
+}
+
+bool ossimPlanetKml::getAllFeatures(ossimPlanetKmlObject::ObjectList& features)
+{
+ std::queue<osg::ref_ptr<ossimPlanetKmlObject> > objectSearchQueue;
+ ossimPlanetKmlObject::ObjectList::iterator iter = theObjectList.begin();
+
+ while(iter != theObjectList.end())
+ {
+ objectSearchQueue.push(*iter);
+ ++iter;
+ }
+
+ while(!objectSearchQueue.empty())
+ {
+ osg::ref_ptr<ossimPlanetKmlObject> topObj = objectSearchQueue.front().get();
+ objectSearchQueue.pop();
+ if(dynamic_cast<ossimPlanetKmlPlacemark*>(topObj.get()))
+ {
+ features.push_back(topObj.get());
+ }
+ else if(dynamic_cast<ossimPlanetKmlGroundOverlay*>(topObj.get()))
+ {
+ features.push_back(topObj.get());
+ }
+ else if(dynamic_cast<ossimPlanetKmlNetworkLink*>(topObj.get()))
+ {
+ features.push_back(topObj.get());
+ }
+ if(topObj->getObjectList().size())
+ {
+ ossim_uint32 idx = 0;
+ ossimPlanetKmlObject::ObjectList& objList = topObj->getObjectList();
+
+ for(idx = 0; idx < objList.size(); ++idx)
+ {
+ objectSearchQueue.push(objList[idx]);
+ }
+ }
+ }
+
+ return (features.size() > 0);
+}
+
+
+#ifdef OSSIMPLANET_HAS_LIBZ
+struct ossimPlantKmzPrivate
+{
+ ossimPlantKmzPrivate()
+ {
+ theArchive = 0;
+ }
+ unzFile theArchive;
+ std::vector<ossimFilename> theFileList;
+};
+static ossimPlantKmzPrivate* ossimPlanetKmzPrivateData(void* pvt)
+{
+ return (ossimPlantKmzPrivate*)pvt;
+}
+#endif
+
+ossimPlanetKmz::ossimPlanetKmz()
+ :ossimPlanetKml()
+{
+#ifdef OSSIMPLANET_HAS_LIBZ
+ thePrivateData = 0;
+#endif
+}
+
+
+ossimPlanetKmz::~ossimPlanetKmz()
+{
+#ifdef OSSIMPLANET_HAS_LIBZ
+ if(thePrivateData)
+ {
+ ossim_uint32 idx = 0;
+ std::vector<ossimFilename>& fileList = ossimPlanetKmzPrivateData(thePrivateData)->theFileList;
+ for(idx = 0; idx < fileList.size(); ++idx)
+ {
+ fileList[idx].remove();
+ fileList[idx].path().remove();
+ }
+ unzClose(ossimPlanetKmzPrivateData(thePrivateData)->theArchive);
+ delete ossimPlanetKmzPrivateData(thePrivateData);
+ thePrivateData = 0;
+ }
+#endif
+
+}
+
+bool ossimPlanetKmz::parse(std::istream& /*in*/)
+{
+ // currently we do not support bridging an istream to libz
+ return false;
+}
+
+bool ossimPlanetKmz::parse(const ossimFilename& file)
+{
+#ifdef OSSIMPLANET_HAS_LIBZ
+ if(thePrivateData)
+ {
+ unzClose(ossimPlanetKmzPrivateData(thePrivateData)->theArchive);
+ delete ossimPlanetKmzPrivateData(thePrivateData);
+ thePrivateData = 0;
+ }
+ thePrivateData = new ossimPlantKmzPrivate;
+ ossimPlanetKmzPrivateData(thePrivateData)->theArchive = unzOpen(file.c_str());
+
+ if(!(ossimPlanetKmzPrivateData(thePrivateData))->theArchive)
+ {
+ delete ossimPlanetKmzPrivateData(thePrivateData);
+ thePrivateData = 0;
+ }
+ if(thePrivateData)
+ {
+ unz_global_info gi;
+ int err;
+ unzFile uf = ossimPlanetKmzPrivateData(thePrivateData)->theArchive;
+ err = unzGetGlobalInfo (uf, &gi);
+ if (err!=UNZ_OK)
+ {
+ return false;
+ }
+ theFilename = file;
+ ossimFilename cacheLocation = getCacheLocation();
+ cacheLocation.createDirectory();
+ ossim_uint32 i = 0;
+ for (i=0;i<gi.number_entry;i++)
+ {
+ std::vector<char> tempFileInfo(2048);
+ unz_file_info file_info;
+ err = unzGetCurrentFileInfo(uf,
+ &file_info,
+ (char*)(&tempFileInfo.front()),
+ tempFileInfo.size(),
+ NULL,
+ 0,NULL,0);
+ if (err!=UNZ_OK)
+ {
+ //ossimNotify(ossimNotifyLevel_WARN) << "Unable to get the global information to read the directory of the passed in KMZ file\n";
+ return false;
+ }
+ ossimFilename outFile;
+ ossimFilename testFile((char*)(&tempFileInfo.front()));
+ if(!testFile.empty())
+ {
+ testFile = cacheLocation.dirCat(testFile.c_str());
+ outFile = testFile;
+ if(testFile.ext().downcase() == "kml")
+ {
+ theFilename = testFile.path().dirCat(theFilename.fileNoExtension()) + ".kml";
+ outFile = theFilename;
+ }
+ if(unzOpenCurrentFile(ossimPlanetKmzPrivateData(thePrivateData)->theArchive) == UNZ_OK)
+ {
+ ossimFilename dir(outFile.path());
+ if(!dir.exists())
+ {
+ dir.createDirectory();
+ }
+ ossimPlanetKmzPrivateData(thePrivateData)->theFileList.push_back(outFile);
+ std::ofstream out(outFile.c_str(),
+ std::ios::out|std::ios::binary);
+
+ if(!out.fail())
+ {
+ std::vector<char> buf(2048);
+ int bytes = 0;
+ while((bytes=unzReadCurrentFile(uf, (char*)(&buf.front()), buf.size()))>0)
+ {
+ out.write((char*)(&buf.front()), bytes);
+ }
+ out.close();
+ }
+ unzCloseCurrentFile(ossimPlanetKmzPrivateData(thePrivateData)->theArchive);
+ }
+ }
+ if ((i+1)<gi.number_entry)
+ {
+ unzGoToNextFile(uf);
+ }
+ }
+ if(theFilename.exists())
+ {
+ ossimRefPtr<ossimXmlDocument> document = new ossimXmlDocument;
+
+ if(document->openFile(theFilename))
+ {
+ return ossimPlanetKml::parse(document);
+ }
+ }
+ }
+#if 0
+ if(thePrivateData&&!ossimPlanetKmzPrivateData(thePrivateData)->theKmlFile.empty())
+ {
+
+ unzFile uf = ossimPlanetKmzPrivateData(thePrivateData)->theArchive;
+ if(unzLocateFile(uf,
+ ossimPlanetKmzPrivateData(thePrivateData)->theKmlFile.c_str(),
+ true) == UNZ_OK)
+ {
+ if(unzOpenCurrentFile(ossimPlanetKmzPrivateData(thePrivateData)->theArchive) == UNZ_OK)
+ {
+ std::stringstream kmlBuf;
+ int bytes = 0;
+ std::vector<char> buf(2048);
+ while((bytes=unzReadCurrentFile(uf, (char*)(&buf.front()), buf.size()))>0)
+ {
+ kmlBuf.write((char*)(&buf.front()), bytes);
+ }
+
+ ossimRefPtr<ossimXmlDocument> document = new ossimXmlDocument;
+
+ if(document->read(kmlBuf))
+ {
+ return ossimPlanetKml::parse(document);
+ }
+ }
+ }
+ }
+#endif
+ return false;
+// if(thePrivateData)
+// {
+// if(ossimPlanetKmzPrivateData(thePrivateData)->theDocFile)
+// {
+// zzip_file_close(ossimPlanetKmzPrivateData(thePrivateData)->theDocFile);
+// }
+// zzip_dir_close(ossimPlanetKmzPrivateData(thePrivateData)->theArchive);
+// ossimPlanetKmzPrivateData(thePrivateData)->theArchive = 0;
+// delete ossimPlanetKmzPrivateData(thePrivateData);
+// thePrivateData = 0;
+
+// }
+// theFilename = file;
+// zzip_error_t errorFlag = ZZIP_NO_ERROR;
+// thePrivateData = new ossimPlantKmzPrivate;
+// ossimPlanetKmzPrivateData(thePrivateData)->theArchive = zzip_dir_open(file.c_str(), &errorFlag);
+// if((!ossimPlanetKmzPrivateData(thePrivateData)->theArchive)||(ZZIP_NO_ERROR != ZZIP_NO_ERROR))
+// {
+// if(ossimPlanetKmzPrivateData(thePrivateData)->theArchive)
+// {
+// zzip_dir_close(ossimPlanetKmzPrivateData(thePrivateData)->theArchive);
+// }
+
+// return false;
+// }
+// ossimPlanetKmzPrivateData(thePrivateData)->theDocFile = zzip_file_open(ossimPlanetKmzPrivateData(thePrivateData)->theArchive,
+// "doc.kml",
+// 0);
+
+// if(!ossimPlanetKmzPrivateData(thePrivateData)->theDocFile)
+// {
+// return false;
+// }
+// std::stringstream buf;
+// std::vector<char> tempBuf(1024);
+
+// int count = 0;
+// while( (count = zzip_file_read(ossimPlanetKmzPrivateData(thePrivateData)->theDocFile,
+// &tempBuf.front(),
+// 1024)) != 0)
+// {
+// buf.write(&tempBuf.front(), count);
+// }
+// buf.seekg(0);
+// ossimRefPtr<ossimXmlDocument> document = new ossimXmlDocument;
+
+// if(document->read(buf))
+// {
+// return ossimPlanetKml::parse(document);
+// }
+
+ return false;
+#else
+ return ossimPlanetKml::parse(file);
+#endif
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetKmlLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlLayer.cpp
new file mode 100644
index 0000000..6e81464
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlLayer.cpp
@@ -0,0 +1,504 @@
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <osgDB/Registry>
+#include <osg/Geode>
+#include <osgUtil/SmoothingVisitor>
+#include <osgUtil/Optimizer>
+#include <osg/Group>
+#include <osg/Texture2D>
+#include <osg/CoordinateSystemNode>
+#include <osg/Billboard>
+#include <osg/DrawPixels>
+#include <osg/MatrixTransform>
+#include <osgUtil/CullVisitor>
+#include <ossim/imaging/ossimMemoryImageSource.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetOssimImage.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/mkUtils.h>
+#include <osg/PolygonOffset>
+#include <osg/PolygonMode>
+#include <osg/TextureRectangle>
+#include <osgDB/ReadFile>
+#include <osg/CoordinateSystemNode>
+#include <osgText/Text>
+#include <time.h>
+#include <ossimPlanet/ossimPlanetLabelGeom.h>
+#include <ossimPlanet/ossimPlanetBillboardIcon.h>
+#include <ossimPlanet/ossimPlanetKmlPlacemarkNode.h>
+#include <ossimPlanet/ossimPlanetKmlScreenOverlayNode.h>
+#include <ossimPlanet/ossimPlanetKml.h>
+#include <ossimPlanet/ossimPlanetKmlNetworkLinkNode.h>
+#include <osgGA/GUIActionAdapter>
+#include <osgGA/EventVisitor>
+#include <wms/wmsCurlMemoryStream.h>
+
+class ossimPlanetStageKmlOperation : public ossimPlanetOperation
+{
+public:
+ ossimPlanetStageKmlOperation(ossimPlanetKmlLayer* layer)
+ :theKmlLayer(layer),
+ theParent(layer)
+ {
+
+ }
+ virtual void run()
+ {
+ if(!theKmlObject.valid())
+ {
+ if(theKmlFile.exists())
+ {
+ osg::ref_ptr<ossimPlanetKml> kmlObject;
+ if(theKmlFile.ext() == "kmz")
+ {
+ kmlObject = new ossimPlanetKmz;
+ }
+ else if(theKmlFile.ext() == "kml")
+ {
+
+ kmlObject = new ossimPlanetKml;
+ }
+ if(kmlObject.valid()&&!kmlObject->parse(theKmlFile))
+ {
+ return;
+ }
+ theKmlObject = kmlObject.get();
+ }
+ }
+ if(theKmlObject.valid())
+ {
+ osg::ref_ptr<ossimXmlNode> xml = new ossimXmlNode;
+ theKmlObject->write(xml.get());
+
+ osg::ref_ptr<ossimPlanetKmlLayerNode> layerNode = 0;
+ if(theKmlObject->getObjectList().size() > 0)
+ {
+ layerNode = setupContainer(theKmlObject.get()).get();
+ }
+ else
+ {
+ layerNode = setupFeature(theKmlObject.get()).get();
+ }
+ if(layerNode.valid())
+ {
+ layerNode->setId(theKmlObject->id());
+ }
+ if(theKmlLayer)
+ {
+ theKmlLayer->readyToAddNode(theParent, layerNode.get());
+ }
+ }
+ }
+ void setParent(osg::Group* parent)
+ {
+ theParent = parent;
+ }
+ void setKmlObject(osg::ref_ptr<ossimPlanetKmlObject> kml)
+ {
+ theKmlObject = kml;
+ }
+ void setFile(const ossimFilename& file)
+ {
+ theKmlFile = file;
+ }
+protected:
+ osg::ref_ptr<ossimPlanetKmlLayerNode> setupContainer(osg::ref_ptr<ossimPlanetKmlObject> container)const
+ {
+ const ossimPlanetKmlObject::ObjectList& objList = container->getObjectList();
+ ossim_uint32 idx = 0;
+ osg::ref_ptr<ossimPlanetKmlLayerNode> group = new ossimPlanetKmlLayerNode;
+ group->setKmlObject(container.get());
+ for(idx = 0; idx < objList.size();++idx)
+ {
+ osg::ref_ptr<ossimPlanetKmlLayerNode> node = 0;
+ if(objList[idx]->getObjectList().size())
+ {
+ node = setupContainer(objList[idx].get());
+ }
+ else
+ {
+ node = setupFeature(objList[idx].get());
+ }
+ if(node.valid())
+ {
+ node->setId(objList[idx]->id());
+ group->addChild(node.get());
+ }
+ }
+ return group.get();
+ }
+
+ osg::ref_ptr<ossimPlanetKmlLayerNode> setupFeature(osg::ref_ptr<ossimPlanetKmlObject> featureObject)const
+ {
+ ossimPlanetKmlFeature* feature = dynamic_cast<ossimPlanetKmlFeature*>(featureObject.get());
+ if(feature)
+ {
+ if(dynamic_cast<ossimPlanetKmlPlacemark*>(feature))
+ {
+ osg::ref_ptr<ossimPlanetKmlPlacemarkNode> result = new ossimPlanetKmlPlacemarkNode(theKmlLayer, featureObject.get());
+
+ if(result->init())
+ {
+ return result.get();
+ }
+ }
+ else if(dynamic_cast<ossimPlanetKmlScreenOverlay*>(feature))
+ {
+ osg::ref_ptr<ossimPlanetKmlScreenOverlayNode> result = new ossimPlanetKmlScreenOverlayNode(theKmlLayer,
+ featureObject.get());
+ if(result->init())
+ {
+ return result.get();
+ }
+ }
+ else if(dynamic_cast<ossimPlanetKmlNetworkLink*>(feature))
+ {
+ ossimPlanetKmlNetworkLink* link = dynamic_cast<ossimPlanetKmlNetworkLink*>(feature);
+ if(link->link())
+ {
+ if(!link->link()->href().empty())
+ {
+ ossimPlanetKmlNetworkLinkNode* node = new ossimPlanetKmlNetworkLinkNode(theKmlLayer,
+ featureObject.get());
+ node->init();
+
+ return node;
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetKmlObject> theKmlObject;
+ ossimFilename theKmlFile;
+ ossimPlanetKmlLayer* theKmlLayer;
+ osg::Group* theParent;
+};
+
+
+osgDB::ReaderWriter::ReadResult ossimPlanetKmlLayerReaderWriter::readNode(
+ const std::string& /* fileName */, const Options*)const
+{
+#if 0
+ osg::ref_ptr<osg::Node> node;
+ if(fileName == "PLW_STAGE_OBJECTS")
+ {
+ std::vector<char> buf(1024);
+ ossimFilename file = theLayer->nextCityDatabase();
+ const ossimPlanetGeoRefModel* model = theLayer->landModel();
+ if(!model) return 0;
+ if(file.isDir())
+ {
+ file = file.dirCat("origins.txt");
+ }
+ if(file.exists())
+ {
+ osg::Vec3d localOrigin;
+ osg::Vec3d origin;
+ double x,y,z,lat,lon,height;
+ ossimFilename path = file.path();
+ theCurrentPlwLocation = path;
+ std::ifstream in(file.c_str(), std::ios::in);
+ if(in.getline(&buf.front(), buf.size()))
+ {
+ std::istringstream header(&buf.front());
+ ossimString field1;
+ header >> field1;
+ if(field1.downcase().contains("origin_wgs84"))
+ {
+ osg::MatrixTransform* modelScaleTransform = new osg::MatrixTransform;
+ node = modelScaleTransform;
+ header >>x>>y>>z>>lat>>lon>>height;
+ double ellipsoidalHeight = model->getHeightAboveEllipsoid(lat, lon);
+
+ modelScaleTransform->setMatrix(osg::Matrixd::scale(1.0/model->getNormalizationScale(),
+ 1.0/model->getNormalizationScale(),
+ 1.0/model->getNormalizationScale()));
+ while(in.getline(&buf.front(), buf.size()))
+ {
+ std::istringstream files(&buf.front());
+ files >>field1>>x>>y>>z>>lat>>lon>>height;
+ osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(std::string(path.dirCat(field1).c_str()));
+ if(loadedModel.get())
+ {
+ osg::MatrixTransform* modelTransform = new osg::MatrixTransform;
+ osg::Matrixd lsrMatrix;
+ ellipsoidalHeight = model->getHeightAboveEllipsoid(lat, lon);
+ model->lsrMatrix(osg::Vec3d(lat, lon, ellipsoidalHeight),
+ lsrMatrix);
+ lsrMatrix(3, 0) *= model->getNormalizationScale();
+ lsrMatrix(3, 1) *= model->getNormalizationScale();
+ lsrMatrix(3, 2) *= model->getNormalizationScale();
+ modelTransform->setMatrix(lsrMatrix);
+ modelTransform->addChild(loadedModel.get());
+ modelScaleTransform->addChild(modelTransform);
+ }
+ }
+ }
+ }
+ theCurrentPlwLocation = "";
+ }
+ }
+ return node.get();
+#endif
+ return 0;
+}
+
+osgDB::ReaderWriter::ReadResult ossimPlanetKmlLayerReaderWriter::readImage(const std::string& fileName, const Options*) const
+{
+ if(theRecurseFlag) return 0;
+ if(ossimFilename(fileName).exists())
+ {
+ theRecurseFlag = true;
+ osgDB::ReaderWriter::ReadResult i = osgDB::Registry::instance()->readImage(fileName, 0);
+ theRecurseFlag = false;
+ if(i.getImage()) return i;
+
+ ossimPlanetOssimImage loader;
+ ossimPlanetImage img;
+ if(loader.loadFile(fileName, img))
+ {
+ osg::Image* i= new osg::Image(img);
+ i->flipVertical();
+ return i;
+ }
+ }
+ if(theCurrentPlwLocation.exists())
+ {
+ ossimFilename tempInputFile(fileName);
+ tempInputFile.convertBackToForwardSlashes();
+ ossimFilename file = theCurrentPlwLocation.dirCat(tempInputFile);
+ if(file.exists())
+ {
+ theRecurseFlag = true;
+ osgDB::ReaderWriter::ReadResult i = osgDB::Registry::instance()->readImage(file.c_str(), 0);
+ theRecurseFlag = false;
+ return i;
+ }
+ }
+ return ReadResult(ReadResult::FILE_NOT_HANDLED);
+}
+
+ossimPlanetKmlLayer::ossimPlanetKmlLayer()
+{
+ theFudgeStamp = new osg::FrameStamp;
+ theReaderWriter = new ossimPlanetKmlLayerReaderWriter(this);
+ osgDB::Registry::instance()->addReaderWriter(theReaderWriter.get());
+ theKmlCacheLocation = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ theKmlCacheLocation = theKmlCacheLocation.dirCat("kml");
+ theReaderWriter->setKmlCacheLocation(theKmlCacheLocation);
+ getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ initializePalettes();
+ theOperationQueue = new ossimPlanetOperationThreadQueue;
+}
+
+void ossimPlanetKmlLayer::traverse(osg::NodeVisitor& nv)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGraphMutex);
+
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(!thePlanet)
+ {
+ thePlanet = ossimPlanet::findPlanet(this);
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNodesToAddListMutex);
+ if(theNodesToAddList.size()>0)
+ {
+ ossim_uint32 idx = 0;
+ for(idx=0;idx<theNodesToAddList.size();++idx)
+ {
+ theNodesToAddList[idx].theParent->addChild(theNodesToAddList[idx].theNode.get());
+ }
+ theNodesToAddList.clear();
+ }
+
+ }
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ if((theReadyToProcessKmlFileList.size() > 0) ||
+ (theReadyToProcessKmlList.size()>0) )
+ {
+ nv.getDatabaseRequestHandler()->requestNodeFile("KML_STAGE_OBJECTS",
+ nv.getNodePath(),
+ 9999999,
+ theFudgeStamp.get(),
+ theRequestRef,
+ 0);
+ }
+ break;
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theNodeList.size(); ++idx)
+ {
+ theNodeList[idx]->accept(nv);
+ }
+ ossimPlanetLayer::traverse(nv);
+}
+
+void ossimPlanetKmlLayer::addKml(osg::ref_ptr<ossimPlanetKmlObject> kml)
+{
+ addKml(this, kml.get());
+}
+
+void ossimPlanetKmlLayer::addKml(osg::ref_ptr<osg::Group> parent,
+ osg::ref_ptr<ossimPlanetKmlObject> kml)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToProcessKmlListMutex);
+ ossimPlanetStageKmlOperation* operation = new ossimPlanetStageKmlOperation(this);
+ operation->setKmlObject(kml);
+ operation->setParent(parent.get());
+ theOperationQueue->add(operation);
+}
+
+void ossimPlanetKmlLayer::addKml(const ossimFilename& kmlFile)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToProcessKmlListMutex);
+ ossimPlanetStageKmlOperation* operation = new ossimPlanetStageKmlOperation(this);
+ operation->setFile(kmlFile);
+ theOperationQueue->add(operation);
+ //theReadyToProcessKmlFileList.push(kmlFile);
+// setRedrawFlag(true);
+}
+
+bool ossimPlanetKmlLayer::addChild( Node *child )
+{
+ return ossimPlanetLayer::addChild(child);
+}
+
+
+osg::ref_ptr<ossimPlanetIconGeom> ossimPlanetKmlLayer::getOrCreateIconEntry(const ossimString& src)
+{
+ osg::ref_ptr<ossimPlanetIconGeom> result = getIconEntry(src);
+ if(result.valid())
+ {
+ return result.get();
+ }
+
+ if(ossimFilename(src).exists())
+ {
+ osg::ref_ptr<osg::Image> img = ossimPlanetImage::readNewOsgImage(ossimFilename(src));
+ osg::ref_ptr<ossimPlanetIconGeom> geom = new ossimPlanetIconGeom;
+ geom->setTexture(new osg::Texture2D(img.get()));
+ theIconMap.insert(std::make_pair(src.c_str(),geom.get()));
+ }
+
+ return getIconEntry(src);
+}
+
+
+osg::ref_ptr<ossimPlanetIconGeom> ossimPlanetKmlLayer::getIconEntry(const ossimString& src)
+{
+ ossimPlanetKmlLayer::IconMap::iterator iter = theIconMap.find(src);
+
+ if(iter!=theIconMap.end())
+ {
+ return iter->second.get();
+ }
+
+ return 0;
+}
+
+
+void ossimPlanetKmlLayer::initializePalettes()
+{
+// ossimFilename paletteDir = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+// paletteDir = paletteDir.dirCat("images");
+// paletteDir = paletteDir.dirCat("icons");
+// if(!paletteDir.exists())
+// {
+// paletteDir = ossimEnvironmentUtility::instance()->getInstalledOssimSupportDir();
+// paletteDir = paletteDir.dirCat("images");
+// paletteDir = paletteDir.dirCat("icons");
+// }
+
+
+// if(paletteDir.exists())
+// {
+// theIconMap.clear();
+// ossim_uint32 idx = 2;
+// for(idx = 1; idx <=5; ++idx)
+// {
+// ossimFilename tempFile = paletteDir;
+// tempFile = tempFile.dirCat(ossimString("palette-") +
+// ossimString::toString(idx)+".png");
+
+// osg::ref_ptr<osg::Image> img = ossimPlanetImage::readNewOsgImage(tempFile);
+// if(img.valid())
+// {
+// std::cout << "Adding icon " << tempFile << std::endl;
+// theIconMap.insert(std::make_pair(tempFile.fileNoExtension(), new osg::Texture2D(img.get())));
+// }
+// }
+// }
+}
+
+void ossimPlanetKmlLayer::deleteNode(const ossimString& id)
+{
+ ossimPlanetKmlLayer::FindNodeVisitor nv(id);
+
+ this->accept(nv);
+ if(nv.layerList().size())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theGraphMutex);
+ FindNodeVisitor::LayerNodeList& layerList = nv.layerList();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < layerList.size(); ++idx)
+ {
+ if(layerList[idx]->getParent(0))
+ {
+ layerList[idx]->getParent(0)->removeChild(layerList[idx].get());
+ notifyRemoveChild(layerList[idx].get());
+ }
+ }
+ }
+}
+
+void ossimPlanetKmlLayer::readyToAddNode(osg::Group* parent,
+ osg::Node* node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNodesToAddListMutex);
+
+ theNodesToAddList.push_back(NodeToAddInfo(parent, node));
+ setRedrawFlag(true);
+}
+
+
+const ossimPlanetGeoRefModel* ossimPlanetKmlLayer::landModel()const
+{
+ if(thePlanet)
+ {
+ return thePlanet->model().get();
+ }
+ return 0;
+}
+
+ossimPlanetGeoRefModel* ossimPlanetKmlLayer::landModel()
+{
+ if(thePlanet)
+ {
+ return thePlanet->model().get();
+ }
+ return 0;
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetKmlLayerNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlLayerNode.cpp
new file mode 100644
index 0000000..239e498
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlLayerNode.cpp
@@ -0,0 +1,50 @@
+#include <ossimPlanet/ossimPlanetKmlLayerNode.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+
+ossimPlanetKmlLayerNode::ossimPlanetKmlLayerNode(ossimPlanetKmlLayer* layer,
+ ossimPlanetKmlObject* obj)
+ :theLayer(layer),
+ theKmlObject(obj)
+{
+ ossimPlanetKmlFeature* feature = dynamic_cast<ossimPlanetKmlFeature*>(obj);
+ if(feature)
+ {
+ setName(feature->name());
+ setDescription(feature->description());
+ setId(feature->id());
+ }
+}
+
+void ossimPlanetKmlLayerNode::traverse(osg::NodeVisitor& nv)
+{
+ if(!enableFlag()) return;
+
+ ossimPlanetNode::traverse(nv);
+}
+
+void ossimPlanetKmlLayerNode::setLayer(ossimPlanetKmlLayer* layer)
+{
+ theLayer = layer;
+}
+
+ossimPlanetKmlLayer* ossimPlanetKmlLayerNode::layer()
+{
+ return theLayer;
+}
+
+void ossimPlanetKmlLayerNode::setKmlObject(ossimPlanetKmlObject* obj)
+{
+ theKmlObject = obj;
+ ossimPlanetKmlFeature* feature = dynamic_cast<ossimPlanetKmlFeature*>(obj);
+ if(feature)
+ {
+ setName(feature->name());
+ setDescription(feature->description());
+ setId(feature->id());
+ }
+}
+
+bool ossimPlanetKmlLayerNode::init()
+{
+ return true;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetKmlNetworkLinkNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlNetworkLinkNode.cpp
new file mode 100644
index 0000000..21d4a6a
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlNetworkLinkNode.cpp
@@ -0,0 +1,108 @@
+#include <ossimPlanet/ossimPlanetKmlNetworkLinkNode.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <wms/wmsCurlMemoryStream.h>
+#include <ossim/base/ossimTempFilename.h>
+
+ossimPlanetKmlNetworkLinkNode::ossimPlanetKmlNetworkLinkNode(ossimPlanetKmlLayer* layer,
+ ossimPlanetKmlObject* obj)
+:ossimPlanetKmlLayerNode(layer, obj)
+{
+ theScheduledFlag = false;
+}
+
+void ossimPlanetKmlNetworkLinkNode::traverse(osg::NodeVisitor& nv)
+{
+ ossimPlanetKmlLayerNode::traverse(nv);
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(!getNumChildren()&&!theScheduledFlag)
+ {
+ if(theKmlData.valid())
+ {
+ if(theLayer)
+ {
+ theScheduledFlag = true;
+ theLayer->addKml(this, theKmlData.get());
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+bool ossimPlanetKmlNetworkLinkNode::init()
+{
+ ossimPlanetKmlNetworkLink* link = dynamic_cast<ossimPlanetKmlNetworkLink*>(theKmlObject.get());
+ if(!link) return false;
+ wmsRefPtr<wmsCurlMemoryStream> curlMemoryStream = new wmsCurlMemoryStream;
+ curlMemoryStream->setMaxRedirects(1);
+ curlMemoryStream->setUrl(link->link()->href().string());
+ bool result = false;
+ ossimTempFilename tempFile("","","kmz");
+ theKmlData = 0;
+// std::cout << "CACHE DIRECTORY ================ " << theKmlObject->getCacheLocation() << std::endl;
+// std::cout << "TRYING LINK ========================== " << link->link()->href() << std::endl;
+ if(ossimFilename(link->link()->href()).ext() == "kmz")
+ {
+ // std::cout << "DOWNLOAD KMZ!!!!!!!!!!!!!!!!!!!" << std::endl;
+ tempFile.generateRandomFile();
+ result = curlMemoryStream->download(tempFile);
+// std::cout << "result ============= " << result << " with file exists " << tempFile << std::endl;
+ }
+ else
+ {
+ result = curlMemoryStream->download();
+// std::cout << "result ============= " << result << std::endl;
+ }
+ if(curlMemoryStream->getStream().valid()&&!tempFile.exists())
+ {
+ ossimRefPtr<wmsMemoryStream> stream = new wmsMemoryStream(curlMemoryStream->getStream()->getBuffer(),
+ curlMemoryStream->getStream()->getBufferSize());
+ if(stream->getBuffer())
+ {
+ stringstream in(ossimString(curlMemoryStream->getStream()->getBuffer(),
+ curlMemoryStream->getStream()->getBuffer()+
+ curlMemoryStream->getStream()->getBufferSize()));
+// std::cout << "PEEEEEK ==== " << (char)in.peek() << std::endl;
+// std::cout << "---------------------------------------------------------------" << std::endl;
+ // std::cout << stream->getBuffer() << std::endl;
+ theKmlData = new ossimPlanetKml;
+ theKmlData->setParent(theKmlObject.get());
+ if(!theKmlData->parse(in, false))
+ {
+ in.clear();
+ in.seekg(0);//, std::ios::beg);
+ if(theKmlData->parse(in, true))
+ {
+ }
+ }
+ else
+ {
+ }
+// std::cout << "==============================================================" << std::endl;
+ }
+ }
+ else if(result&&tempFile.exists())
+ {
+ theKmlData = new ossimPlanetKmz;
+ theKmlData->setParent(theKmlObject.get());
+ if(!theKmlData->parse(tempFile))
+ {
+// std::cout << "NO KMZ!!!!!!!!!!!!!!!!!!!" << std::endl;
+ theKmlData = 0;
+ }
+ else
+ {
+// std::cout << "GOT KMZ!!!!!!!!!!!!!!!!!!!" << std::endl;
+ }
+ }
+
+ return result;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetKmlPlacemarkNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlPlacemarkNode.cpp
new file mode 100644
index 0000000..d918d17
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlPlacemarkNode.cpp
@@ -0,0 +1,1176 @@
+#include <ossimPlanet/ossimPlanetKmlPlacemarkNode.h>
+#include <osgUtil/IntersectVisitor>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <ossimPlanet/ossimPlanetCubeGrid.h>
+#include <osg/LineWidth>
+#include <osg/PolygonOffset>
+#include <osg/PolygonMode>
+#include <osg/CullSettings>
+#include <osgUtil/SmoothingVisitor>
+#include <osgUtil/TriStripVisitor>
+#include <osgUtil/CullVisitor>
+#include <osgUtil/Tessellator>
+#include <osg/TriangleFunctor>
+#include <osg/ShadeModel>
+#include <osg/Point>
+#include <osg/Node>
+#include <osgDB/ReadFile>
+
+
+void ossimPlanetKmlPlacemarkNode::PlacemarkGeometryDraw::drawImplementation(osg::RenderInfo& renderInfo,
+ const osg::Drawable* drawable)const
+{
+ osg::Drawable* nonConstDrawable = const_cast<osg::Drawable*>(drawable);
+ osg::Geometry* geom = dynamic_cast<osg::Geometry*>(nonConstDrawable);
+ if(geom)
+ {
+ osg::Vec4Array* array = dynamic_cast<osg::Vec4Array*>(geom->getColorArray());
+ if(array&&array->size()==1)
+ {
+ float previous = (*array)[0][3];
+ (*array)[0][3] *=theOpacity;
+ geom->setColorArray(array);
+ drawable->drawImplementation(renderInfo);
+ (*array)[0][3] = previous;
+ geom->setColorArray(array);
+
+ }
+ else
+ {
+ drawable->drawImplementation(renderInfo);
+ }
+ }
+ else
+ {
+ drawable->drawImplementation(renderInfo);
+ }
+}
+
+ossimPlanetKmlPlacemarkNode::ossimPlanetKmlPlacemarkNode(ossimPlanetKmlLayer* layer,
+ ossimPlanetKmlObject* obj)
+ :ossimPlanetKmlLayerNode(layer, obj)
+{
+// setCullingActive(false);
+ getOrCreateStateSet()->setMode( GL_LIGHTING,
+ osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF );
+ theCulledFlag = false;
+}
+
+
+void ossimPlanetKmlPlacemarkNode::traverse(osg::NodeVisitor& nv)
+{
+ if(!enableFlag()) return;
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ theCulledFlag = false;
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(theLod.valid())
+ {
+// float opacity = 1.0;
+ // divide by root 2
+ // this is a unit square so the radius is more than likely similar to the radius along the
+ // diagonal. We just need a crude approximation to give the visual afect we want.
+ //
+ float pixelSize = cullVisitor->clampedPixelSize(theCenter, theRadius)/1.41421356237309504880;
+ if(pixelSize > theLod->minLodPixels())
+ {
+ ossim_int32 maxLod = theLod->maxLodPixels();
+ if((maxLod > 0)&&(pixelSize > maxLod))
+ {
+ theCulledFlag = true;
+ return;
+ }
+ }
+ else
+ {
+ theCulledFlag = true;
+ return;
+ }
+ if(theLod->minFadeExtent()&&
+ theLod->maxFadeExtent()&&
+ (theLod->minFadeExtent()<theLod->maxFadeExtent()))
+ {
+ if (pixelSize < theLod->minLodPixels())
+ {
+ theFadeAlpha=0;
+ }
+ else if((pixelSize < (theLod->minLodPixels() + theLod->minFadeExtent())))
+ {
+ theFadeAlpha=(pixelSize - theLod->minLodPixels())/theLod->minFadeExtent();
+ }
+ else if(pixelSize < (theLod->maxLodPixels() - theLod->maxFadeExtent()))
+ {
+ theFadeAlpha=1;
+ }
+ else if (pixelSize < theLod->maxLodPixels())
+ {
+ theFadeAlpha=(theLod->maxLodPixels()-pixelSize)/theLod->maxFadeExtent();
+ }
+ else
+ {
+ theFadeAlpha=0;
+ }
+ if(theDraw.valid())
+ {
+ theDraw->theOpacity = theFadeAlpha;
+ }
+ if(theFadeAlpha==0)
+ {
+ theCulledFlag = true;
+ return;
+ }
+ }
+ else
+ {
+ if(theDraw.valid())
+ {
+ theDraw->theOpacity = 1.0;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if(theCulledFlag)
+ {
+ return;
+ }
+ }
+ }
+ if(theKmlGeometries.valid())
+ {
+ if(dynamic_cast<osgUtil::IntersectVisitor*>(&nv))
+ {
+ if(theKmlPickableGeometries.valid())
+ {
+ theKmlPickableGeometries->accept(nv);
+ }
+ }
+ else
+ {
+ theKmlGeometries->accept(nv);
+ }
+ }
+}
+#if 0
+static std::ostream& operator << (std::ostream& out, const osg::Vec3d& src)
+{
+ out << "<" << src[0] <<", " << src[1] << ", " << src[2];
+ return out;
+}
+static std::ostream& operator << (std::ostream& out, const osg::Vec4& src)
+{
+ out << "<" << src[0] <<", " << src[1] << ", " << src[2] << ", " << src[3];
+ return out;
+}
+#endif
+
+class ossimPlanetKmlTextShiftUpdate : public osg::Drawable::UpdateCallback
+{
+public:
+ ossimPlanetKmlTextShiftUpdate(ossimPlanetBillboardIcon* icon,
+ osg::ClusterCullingCallback* clusterCallback,
+ osg::ref_ptr<osg::Drawable::UpdateCallback> oldCallback=0)
+ :theIcon(icon),
+ theCallback(clusterCallback),
+ theOldCallback(oldCallback)
+ {}
+ virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
+ {
+ osgText::Text* text = dynamic_cast<osgText::Text*>(drawable);
+ if(text&&theIcon)
+ {
+ if(theOldCallback.valid())
+ {
+ theOldCallback->update(nv, drawable);
+ }
+ osg::Vec3d labelShift(0.0,0.0,0.0);
+ osg::BoundingSphere bs = theIcon->getBound();
+ if(bs.valid())
+ {
+ labelShift[2] = bs.radius()*1.5;
+ }
+
+ if(!ossim::almostEqual(labelShift[2],
+ (double)text->getPosition()[2],
+ DBL_EPSILON))
+ {
+ text->setPosition(labelShift);
+// if(theCallback)
+// {
+// theCallback->set(labelShift,
+// theCallback->getNormal(),
+// theCallback->getDeviation(),
+// theCallback->getRadius());
+// }
+ text->dirtyBound();
+ }
+ }
+ }
+ ossimPlanetBillboardIcon* theIcon;
+ osg::ClusterCullingCallback* theCallback;
+ osg::ref_ptr<osg::Drawable::UpdateCallback> theOldCallback;
+};
+bool ossimPlanetKmlPlacemarkNode::init()
+{
+ if(!theLayer) return false;
+ ossimPlanetGeoRefModel* landModel = theLayer->landModel();
+ ossimPlanetKmlPlacemark* placemark = dynamic_cast<ossimPlanetKmlPlacemark*>(theKmlObject.get());
+ if(!placemark||!landModel) return false;
+
+ std::vector<osg::ref_ptr<ossimPlanetKmlGeometry> > primitiveGeomList;
+ theKmlGeometries = new osg::Group;
+ theKmlPickableGeometries = new osg::Group;
+
+ // load placemark feature
+ osg::ref_ptr<ossimPlanetKmlGeometry> geom = placemark->getGeometry();
+ if(geom.valid())
+ {
+ if(geom->toMultiGeometry())
+ {
+ std::vector<osg::ref_ptr<ossimPlanetKmlGeometry> >& multiGeomList = geom->toMultiGeometry()->geomtryList();
+
+ primitiveGeomList.insert(primitiveGeomList.begin(),
+ multiGeomList.begin(),
+ multiGeomList.end());
+ }
+ else
+ {
+ primitiveGeomList.push_back(geom.get());
+ }
+ }
+
+ theRegion = placemark->region();
+ if(theRegion.valid())
+ {
+ theLod = theRegion->lod();
+ }
+ else
+ {
+ theLod = 0;
+ }
+ // let's setup the global stuff that all geometries will need access to to initialize itself
+ //
+ static osg::ref_ptr<osgText::Font> defaultFont = osgText::readFontFile("fonts/arial.ttf");
+ ossimPlanetKml* kml = dynamic_cast<ossimPlanetKml*>(placemark->getRoot(placemark));
+ theNormalizationScale = landModel->getNormalizationScale();
+ const ossimPlanetKmlStyleSelector* styleSelector = placemark->getStyleSelector().get();
+ ossimString styleUrl = placemark->styleUrl();
+
+ if(kml)
+ {
+// std::cout << "STYLE URL == " << styleUrl << std::endl;
+ // check for the inline style
+ if(!styleSelector&&!styleUrl.empty())
+ {
+ if(*(styleUrl.begin()) == '#')
+ {
+ // no inline style
+ // Now check for shared style
+ const osg::ref_ptr<ossimPlanetKmlObject> obj = kml->findById(styleUrl.after("#"));
+ if(obj.valid())
+ {
+ styleSelector = dynamic_cast<const ossimPlanetKmlStyleSelector*>(obj.get());
+ }
+ }
+ }
+ }
+
+ const ossimPlanetKmlStyle* normalStyle = 0;
+ const ossimPlanetKmlStyle* highlightStyle = 0;
+ const ossimPlanetKmlIconStyle* normalIconStyle = 0;
+ const ossimPlanetKmlLabelStyle* normalLabelStyle = 0;
+ // const ossimPlanetKmlLineStyle* normalLineStyle = 0;
+ const ossimPlanetKmlPolyStyle* normalPolyStyle = 0;
+ // const ossimPlanetKmlBalloonStyle* normalBalloonStyle = 0;
+ const ossimPlanetKmlStyleMap* styleMap = 0;
+
+ if(styleSelector)
+ {
+ styleMap = styleSelector->toStyleMap();
+ if(styleMap&&kml)
+ {
+ const ossimPlanetKmlObject* obj = kml->findById(styleMap->normalUrl().after("#")).get();
+ styleSelector = dynamic_cast<const ossimPlanetKmlStyleSelector*>(obj);
+ if(styleSelector)
+ {
+// std::cout << "Found normal style!" << std::endl;
+ normalStyle = styleSelector->toStyle();
+ }
+ obj = kml->findById(styleMap->highlightUrl().after("#")).get();
+ styleSelector = dynamic_cast<const ossimPlanetKmlStyleSelector*>(obj);
+ if(styleSelector)
+ {
+ highlightStyle = styleSelector->toStyle();
+ }
+ }
+ else
+ {
+ normalStyle = styleSelector->toStyle();
+ }
+
+ if(normalStyle)
+ {
+ normalIconStyle = normalStyle->iconStyle().get();
+ normalLabelStyle = normalStyle->labelStyle().get();
+ // normalLineStyle = normalStyle->lineStyle().get();
+ normalPolyStyle = normalStyle->polyStyle().get();
+ // normalBalloonStyle = normalStyle->balloonStyle().get();
+ if(normalPolyStyle)
+ {
+// std::cout << "OUTLINE? " << normalPolyStyle->getOutlineFlag() << std::endl;
+ }
+ }
+ }
+ if(highlightStyle)
+ {
+ if(highlightStyle->iconStyle().valid())
+ {
+ }
+ if(highlightStyle->labelStyle().valid())
+ {
+ }
+ if(highlightStyle->lineStyle().valid())
+ {
+ }
+ }
+// if(placemark->getCenter(lat, lon, alt))
+// {
+// llh = osg::Vec3d(lat, lon, alt);
+// double geoidOffset = landModel->getGeoidOffset(lat,
+// lon);
+// if(!ossim::isnan(geoidOffset))
+// {
+// llh[2]+=geoidOffset;
+// }
+// }
+ ossimPlanetCubeGrid grid;
+ ossimPlanetGridUtility::GridPoint gridPt;
+ for(std::vector<osg::ref_ptr<ossimPlanetKmlGeometry> >::const_iterator iter = primitiveGeomList.begin();
+ iter != primitiveGeomList.end();
+ ++iter)
+ {
+ bool needsReTessFlag = false;
+ double lat, lon, alt;
+ osg::Vec3d llh;;
+ if(!(*iter)->getCenter(lat, lon, alt))
+ {
+ continue;
+ }
+ llh = osg::Vec3d(lat, lon, alt);
+ llh[2] += landModel->getGeoidOffset(lat,
+ lon);
+ osg::Matrixd localToWorld;
+ osg::Matrixd inverseLocalToWorld;
+ landModel->lsrMatrix(llh, localToWorld);
+ osg::ref_ptr<osg::MatrixTransform> localToWorldTransform = new osg::MatrixTransform;
+ osg::ref_ptr<osg::MatrixTransform> localToWorldPickableTransform = new osg::MatrixTransform;
+ localToWorldTransform->setMatrix(localToWorld);
+ localToWorldPickableTransform->setMatrix(localToWorld);
+ inverseLocalToWorld.invert(localToWorld);
+ osg::Vec3d ecef;
+ osg::Vec3d normal;
+ landModel->forward(llh, ecef);
+ landModel->normal(ecef, normal);
+ normal.normalize();
+// osg::Vec3d centerGridLatLon;
+// std::cout << "llh before = " << llh[0] << ", " << llh[1] << ", " << llh[2] << "\n";
+// grid.getGridPoint(gridPt,
+// llh);
+// std::cout << "gridPt before = " << gridPt.theGlobalGridPoint[0] << ", " << gridPt.theGlobalGridPoint[1] << "\n";
+// grid.getCenterGridPoint(gridPt,
+// 5,
+// llh);
+// grid.getLatLon(centerGridLatLon,
+// gridPt);
+
+// centerGridLatLon[2] = landModel->getHeightAboveEllipsoid(centerGridLatLon[0],
+// centerGridLatLon[1]);
+ // landModel->lsrMatrix(centerGridLatLon, localToWorld);
+// localToWorldTransform->setMatrix(localToWorld);
+// localToWorldPickableTransform->setMatrix(localToWorld);
+// inverseLocalToWorld.invert(localToWorld);
+
+// std::cout << "llh after = " << centerGridLatLon[0] << ", " << centerGridLatLon[1] << ", " << centerGridLatLon[2] << "\n";
+ osg::Vec3d localNormal = osg::Matrixd::transform3x3(localToWorld, normal);
+ osg::ref_ptr<ossimPlanetKmlGeometry> geom = *iter;
+ osg::ref_ptr<osg::Vec3Array> verts = new osg::Vec3Array;
+ osg::ref_ptr<osg::Vec3Array> extrusionVerts = new osg::Vec3Array;
+ std::vector<std::pair<ossim_uint32, ossim_uint32> > extrusionGroups; // will be used for extrusions
+ osg::ref_ptr<osg::Geometry> kmlPrimitiveGeom = new osg::Geometry;
+ double minHeight, maxHeight;
+ ossimPlanetAltitudeMode altMode = geom->altitudeMode();
+ bool needsOutline = false;
+ double offset = 0.0;
+ osg::ref_ptr<osg::Geode> geometryNode = new osg::Geode;
+ // bool computeNormals = false;
+ bool extrudeFlag = false;
+ // bool hasInnerRings = false;
+
+ if(geom->toPoint())
+ {
+ ossimPlanetKmlPoint* point = geom->toPoint();
+ const ossimPlanetKmlGeometry::PointListType& pointList = point->pointList();
+ if(pointList.size())
+ {
+ // we actually need to adjust the Matrix transform for points since we need to center
+ // the location based on altitude type
+ //
+ //
+ osg::Vec3d tempLlh (pointList[0][1],
+ pointList[0][0],
+ convertHeight(pointList[0], altMode, landModel));
+ landModel->lsrMatrix(tempLlh, localToWorld);
+ localToWorldTransform->setMatrix(localToWorld);
+ localToWorldPickableTransform->setMatrix(localToWorld);
+ inverseLocalToWorld.invert(localToWorld);
+
+ convertPointsToLocalCoordinates(verts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ altMode,
+ minHeight,
+ maxHeight);
+
+ if(point->extrudeFlag()&&(altMode!=ossimPlanetAltitudeMode_CLAMP_TO_GROUND))
+ {
+ extrudeFlag = true;
+ // computeNormals = false;
+ convertPointsToLocalCoordinates(extrusionVerts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ ossimPlanetAltitudeMode_CLAMP_TO_GROUND,
+ minHeight,
+ maxHeight);
+ extrusionGroups.push_back(std::make_pair(0, 1));
+ }
+ }
+ osg::ref_ptr<ossimPlanetFadeText> text;
+ osg::ref_ptr<osg::ClusterCullingCallback> textCull;
+ osg::ref_ptr<osg::Geode> textGeometry;
+ osg::ref_ptr<ossimPlanetBillboardIcon> billboardIcon;
+ if(!placemark->name().empty())
+ {
+ text = new ossimPlanetFadeText();
+ text->setText(placemark->name());
+ text->setFont(defaultFont.get());
+ text->setBackdropType(osgText::Text::OUTLINE);
+ osg::Vec3d textEcef(0.0,0.0,0.0);//1000.0/landModel->getNormalizationScale());
+ text->setPosition(textEcef);
+ text->setCharacterSize(30000.0f/landModel->getNormalizationScale());
+ text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
+ text->setAutoRotateToScreen(true);
+ text->setAlignment(osgText::Text::CENTER_BOTTOM);
+ textCull = new osg::ClusterCullingCallback(textEcef, localNormal, 0.0);
+ text->setClusterCullingCallback(textCull.get());
+ textGeometry = new osg::Geode;
+ textGeometry->addDrawable(text.get());
+ textGeometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+ }
+ if(normalIconStyle)
+ {
+
+ const osg::ref_ptr<ossimPlanetKmlIcon> icon = normalIconStyle->icon();
+ if(icon.valid())
+ {
+ ossimFilename file = icon->download();
+ osg::ref_ptr<osg::Image> img;
+ if(file.exists())
+ {
+ osg::ref_ptr<ossimPlanetIconGeom> geom = theLayer->getOrCreateIconEntry(file);
+
+ if(geom.valid())
+ {
+ billboardIcon = new ossimPlanetBillboardIcon;
+ billboardIcon->setGeom(geom.get());
+ }
+ }
+ }
+ }
+
+ localToWorldPickableTransform->setMatrix(localToWorld);
+ if(billboardIcon.valid())
+ {
+
+ localToWorldTransform->addChild(billboardIcon.get());
+ localToWorldPickableTransform->addChild(billboardIcon.get());
+ if(text.get()&&textCull.get())
+ {
+ text->setUpdateCallback(new ossimPlanetKmlTextShiftUpdate(billboardIcon.get(),
+ textCull.get(),
+ text->getUpdateCallback()));
+ }
+ }
+ if(textGeometry.valid())
+ {
+ localToWorldTransform->addChild(textGeometry.get());
+ }
+ if(!billboardIcon.valid())
+ {
+ localToWorldPickableTransform->addChild(textGeometry.get());
+
+ }
+
+ if(normalLabelStyle&&text.valid())
+ {
+ ossimString color = normalLabelStyle->color();
+ if(color != "")
+ {
+ ossim_uint8 r, g, b, a;
+ ossimPlanetKmlColorToRGBA(r,g,b,a, color);
+ if(normalLabelStyle->colorMode() == ossimPlanetKmlColorMode_RANDOM)
+ {
+ double tr = (double)rand()/(double)RAND_MAX;
+ double tg = (double)rand()/(double)RAND_MAX;
+ double tb = (double)rand()/(double)RAND_MAX;
+ r = (ossim_uint8)(tr*r);
+ g = (ossim_uint8)(tg*g);
+ b = (ossim_uint8)(tb*b);
+ }
+ text->setColor(osg::Vec4(r/255.0,g/255.0,b/255.0,a/255.0) );
+ }
+ }
+ if(localToWorldPickableTransform.valid())
+ {
+ theKmlPickableGeometries->addChild(localToWorldPickableTransform.get());
+ }
+ } // end toPoint
+ else if(geom->toLineString())
+ {
+ ossimPlanetKmlLineString* lineString = geom->toLineString();
+ const ossimPlanetKmlGeometry::PointListType& pointList = lineString->pointList();
+ if(pointList.size())
+ {
+ convertPointsToLocalCoordinates(verts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ altMode,
+ minHeight,
+ maxHeight);
+ if(lineString->extrudeFlag()&&(altMode!=ossimPlanetAltitudeMode_CLAMP_TO_GROUND))
+ {
+ extrudeFlag = true;
+ // computeNormals = true;
+ convertPointsToLocalCoordinates(extrusionVerts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ ossimPlanetAltitudeMode_CLAMP_TO_GROUND,
+ minHeight,
+ maxHeight);
+ extrusionGroups.push_back(std::make_pair((ossim_uint32)0,
+ (ossim_uint32)verts->size()));
+ }
+ kmlPrimitiveGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,verts->size()));
+ }
+ }
+ else if(geom->toLinearRing())
+ {
+ ossimPlanetKmlLinearRing* linearRing = geom->toLinearRing();
+
+ const ossimPlanetKmlGeometry::PointListType& pointList = linearRing->pointList();
+ if(pointList.size())
+ {
+ convertPointsToLocalCoordinates(verts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ altMode,
+ minHeight,
+ maxHeight);
+ if(linearRing->extrudeFlag()&&(altMode!=ossimPlanetAltitudeMode_CLAMP_TO_GROUND))
+ {
+ extrudeFlag = true;
+ // computeNormals = true;
+ convertPointsToLocalCoordinates(extrusionVerts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ ossimPlanetAltitudeMode_CLAMP_TO_GROUND,
+ minHeight,
+ maxHeight);
+ extrusionGroups.push_back(std::make_pair((ossim_uint32)0,
+ (ossim_uint32)verts->size()));
+
+ }
+ kmlPrimitiveGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,verts->size()));
+ }
+ }
+ else if(geom->toPolygon())
+ {
+ ossimPlanetKmlLinearRing* linearRing = geom->toPolygon()->outerBoundary().get();
+ const ossimPlanetKmlPolygon::InnerBoundaryList& innerRings = geom->toPolygon()->innerBoundaryList();
+ extrudeFlag = geom->toPolygon()->extrudeFlag();
+ ossim_uint32 startGroupIdx = 0;
+
+ if(linearRing)
+ {
+ const ossimPlanetKmlGeometry::PointListType& pointList = linearRing->pointList();
+ if(pointList.size())
+ {
+ convertPointsToLocalCoordinates(verts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ altMode,
+ minHeight,
+ maxHeight);
+ if(extrudeFlag&&(altMode!=ossimPlanetAltitudeMode_CLAMP_TO_GROUND))
+ {
+ needsReTessFlag = true;
+ // computeNormals = true;
+ convertPointsToLocalCoordinates(extrusionVerts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ ossimPlanetAltitudeMode_CLAMP_TO_GROUND,
+ minHeight,
+ maxHeight);
+ extrusionGroups.push_back(std::make_pair((ossim_uint32)startGroupIdx,
+ (ossim_uint32)pointList.size()));
+ startGroupIdx += pointList.size();
+ }
+ else
+ {
+ offset = ossim::max((maxHeight-minHeight)*.25, 5.0);
+ }
+ }
+ }
+ if(innerRings.size() > 0)
+ {
+ // hasInnerRings = true;
+ needsReTessFlag = true;
+ ossim_uint32 innerRingIdx = 0;
+ for(innerRingIdx = 0; innerRingIdx < innerRings.size(); ++innerRingIdx)
+ {
+ const ossimPlanetKmlGeometry::PointListType& pointList = innerRings[innerRingIdx]->pointList();
+ convertPointsToLocalCoordinates(verts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ altMode,
+ minHeight,
+ maxHeight);
+ if(extrudeFlag)
+ {
+ convertPointsToLocalCoordinates(extrusionVerts.get(),
+ pointList,
+ inverseLocalToWorld,
+ landModel,
+ ossimPlanetAltitudeMode_CLAMP_TO_GROUND,
+ minHeight,
+ maxHeight);
+ extrusionGroups.push_back(std::make_pair((ossim_uint32)startGroupIdx,
+ (ossim_uint32)(pointList.size())));
+ startGroupIdx += pointList.size();
+
+ }
+ if(!extrudeFlag)
+ {
+ offset = ossim::max(offset, ossim::max((maxHeight-minHeight)*.25, 5.0));
+ }
+ }
+ }
+ kmlPrimitiveGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,verts->size()));
+
+ if(!needsReTessFlag)
+ {
+ if(normalStyle->polyStyle().get())
+ {
+ const osg::ref_ptr<ossimPlanetKmlPolyStyle> polyStyle = normalStyle->polyStyle();
+ if(polyStyle.valid())
+ {
+ polyStyle->theColor = placemark->getPColor();
+ polyStyle->clearFields();
+ if(polyStyle->getFillFlag())
+ {
+ needsReTessFlag = true;
+ }
+ }
+ }
+ }
+ }// toPolygon
+ else if(geom->toModel())
+ {
+ const ossimPlanetKmlModel* model = geom->toModel();
+ osg::ref_ptr<ossimPlanetKmlLocation> location = model->location();
+ osg::ref_ptr<ossimPlanetKmlOrientation> orientation = model->orientation();
+ const osg::ref_ptr<ossimPlanetKmlScale> scale = model->scale();
+ osg::ref_ptr<ossimPlanetKmlLink> link = model->link();
+ double heading = 0.0, pitch = 0.0, roll = 0.0;
+ double scalex = 1.0, scaley=1.0, scalez=1.0;
+ if(orientation.valid())
+ {
+ heading = orientation->heading();
+ pitch = orientation->pitch();
+ roll = orientation->roll();
+ }
+ if(scale.valid())
+ {
+ scalex = scale->x();
+ scaley = scale->y();
+ scalez = scale->z();
+ }
+ if(location.get()&&link.get())
+ {
+ osg::Vec3d kmlPoint(location->longitude(),
+ location->latitude(),
+ location->altitude());
+ osg::Vec3d tempLlh(kmlPoint[1],
+ kmlPoint[0],
+ convertHeight(kmlPoint, altMode, landModel));
+// std::cout << "H = " << tempLlh[2] << std::endl;
+ landModel->lsrMatrix(tempLlh, localToWorld, heading);
+ localToWorld = (osg::Matrixd::scale(scalex, scaley, scalez)*
+ osg::Matrixd::rotate(pitch, osg::Vec3d(1.0, 0.0, 0.0))*
+ osg::Matrixd::rotate(roll, osg::Vec3d(0.0, 1.0, 0.0)))*localToWorld;
+ localToWorldTransform->setMatrix(localToWorld);
+ localToWorldPickableTransform->setMatrix(localToWorld);
+ ossimFilename modelName = link->download();
+ if(modelName.exists())
+ {
+ osg::NotifySeverity severity = osg::getNotifyLevel();
+ osg::setNotifyLevel(osg::ALWAYS);
+ osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(std::string(modelName.c_str()));
+ osg::setNotifyLevel(severity);
+// osgDB::ReaderWriter::ReadResult result = osgDB::Registry::instance()->readNode(modelName.c_str(), 0);
+ if(loadedModel.valid())
+ {
+ std::ifstream in(modelName.c_str());
+ std::vector<char> buf(4048);
+ in.read(&buf.front(), buf.size());
+ double scaleMultiplier = 1.0;
+ if(in.gcount() > 0)
+ {
+ ossimString s(buf.begin(),
+ buf.begin() + in.gcount());
+ ossimString::size_type beginPos = s.find("<asset>");
+ if(beginPos != std::string::npos)
+ {
+ ossimString assetXmlNode;
+ ossimString::size_type endPos = s.find("</asset>");
+ if(endPos != std::string::npos)
+ {
+ assetXmlNode = ossimString(buf.begin() + beginPos,
+ buf.begin() + endPos+8);
+ ossimRefPtr<ossimXmlNode> xmlNode = new ossimXmlNode;
+ std::istringstream inStringStream(assetXmlNode);
+ if(xmlNode->read(inStringStream))
+ {
+ ossimRefPtr<ossimXmlNode> unitNode = xmlNode->findFirstNode("unit");
+ if(unitNode.valid())
+ {
+ ossimString scaleValue;
+ if(unitNode->getAttributeValue(scaleValue, "meter"))
+ {
+ scaleMultiplier = scaleValue.toDouble();
+ }
+ }
+ }
+ }
+ }
+ }
+// osg::Vec3d v;
+// landModel->forward(tempLlh, v);
+ osg::MatrixTransform* modelTransform = new osg::MatrixTransform;
+ double scale2 = (1.0/landModel->getNormalizationScale());
+ modelTransform->setMatrix(osg::Matrixd::scale((scale2*scaleMultiplier),
+ (scale2*scaleMultiplier),
+ (scale2*scaleMultiplier)));
+ modelTransform->addChild(loadedModel.get());
+ modelTransform->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON);
+
+// modelScaleTransform->addChild(modelTransform);
+ localToWorldTransform->addChild(modelTransform);
+ ossimSetNonPowerOfTwoTextureVisitor nv;
+ localToWorldTransform->accept(nv);
+ }
+ }
+ }
+ }
+// }
+
+ if(extrudeFlag)
+ {
+ extrude(kmlPrimitiveGeom.get(),
+ verts.get(),
+ extrusionVerts.get(),
+ extrusionGroups);
+ }
+
+ if(altMode==ossimPlanetAltitudeMode_CLAMP_TO_GROUND&&offset > 0.0)
+ {
+ kmlPrimitiveGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::PolygonOffset(-offset, -offset),
+ osg::StateAttribute::ON);
+ }
+ else
+ {
+ offset = 0.0;
+ }
+
+
+ if(offset > 0.0)//||(altMode == ossimPlanetAltitudeMode_CLAMP_TO_GROUND))
+ {
+ kmlPrimitiveGeom->setCullCallback(new osg::ClusterCullingCallback(osg::Vec3d(0.0,0.0,0.0),
+ localNormal,
+ 0.0));
+ }
+
+
+ kmlPrimitiveGeom->setSupportsDisplayList(true);
+ kmlPrimitiveGeom->setUseDisplayList(true);
+
+// kmlPrimitiveGeom->setSupportsDisplayList(!theLod.valid());
+ kmlPrimitiveGeom->setVertexArray(verts.get());
+
+ osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
+ float lineWidth = 2.0;
+ osg::Vec4 lineColor(1.0,1.0,1.0,1.0);
+ osg::Vec4 polyColor(1.0,1.0,1.0,1.0);
+ osg::PolygonMode::Mode polygonStyleMode = osg::PolygonMode::LINE;
+ bool polyStyleOutline = false;
+ if(normalStyle)
+ {
+ // bool lineColorSetFlag;
+ const osg::ref_ptr<ossimPlanetKmlLineStyle> lineStyle = normalStyle->lineStyle();
+ if(lineStyle.valid())
+ {
+ ossim_uint8 r,g,b,a;
+ ossimPlanetKmlColorToRGBA(r,g,b,a,lineStyle->color());
+ // lineColorSetFlag = true;
+ lineColor = osg::Vec4(r/255.0,
+ g/255.0,
+ b/255.0,
+ a/255.0);
+ lineWidth = lineStyle->width();
+ if(lineWidth != 0.0)
+ {
+ kmlPrimitiveGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(lineWidth),
+ osg::StateAttribute::ON);
+ }
+ }
+ if(normalStyle->polyStyle().get())
+ {
+ const osg::ref_ptr<ossimPlanetKmlPolyStyle> polyStyle = normalStyle->polyStyle();
+ if(polyStyle.valid())
+ {
+ ossim_uint8 r,g,b,a;
+ ossimPlanetKmlColorToRGBA(r,g,b,a, polyStyle->color());
+ // lineColorSetFlag = true;
+ polyColor = osg::Vec4(r/255.0,
+ g/255.0,
+ b/255.0,
+ a/255.0);
+
+ if(polyStyle->getFillFlag())
+ {
+ polygonStyleMode = osg::PolygonMode::FILL;
+ }
+ if(polyStyle->getOutlineFlag())
+ {
+ polyStyleOutline = true;//(polygonStyleMode == osg::PolygonMode::FILL);
+// ossimNotify(ossimNotifyLevel_WARN) << "Outlining not supported yet in Kml drawing" << std::endl;
+ }
+ }
+ kmlPrimitiveGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,
+ polygonStyleMode),
+ osg::StateAttribute::ON);
+ }
+ }
+ // check to see if we need to do an outline
+ // If we are extruded or a plygon and have the outline flag enabled
+ //
+ if(geom->toPolygon())
+ {
+ if(polyStyleOutline&&(polygonStyleMode==osg::PolygonMode::FILL))
+ {
+ needsOutline = true;
+ }
+ }
+ else if(extrudeFlag&&!geom->toPoint()&&!geom->toPolygon())
+ {
+ needsOutline = true;
+ }
+
+
+ if((extrudeFlag&&!geom->toPoint())||
+ ((geom->toPolygon()&&(polygonStyleMode==osg::PolygonMode::FILL))))
+ {
+ color->push_back(polyColor);
+ }
+ else
+ {
+ color->push_back(lineColor);
+ }
+// if((*color)[0][3] < 1.0)
+ {
+ kmlPrimitiveGeom->getOrCreateStateSet()->setMode(GL_BLEND,osg::StateAttribute::ON);
+ }
+ kmlPrimitiveGeom->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
+ kmlPrimitiveGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
+ kmlPrimitiveGeom->setColorArray(color.get());
+
+
+ osg::ref_ptr<osg::Geometry> outlineGeom;
+#if 1
+ if(needsOutline)
+ {
+ outlineGeom = new osg::Geometry(*kmlPrimitiveGeom, osg::CopyOp::DEEP_COPY_ALL);
+ if(!geom->toPoint()&&extrudeFlag)
+ {
+ // we will only keep the walls around. Walls are after the root primitive
+ // when extruding
+ //
+ outlineGeom->removePrimitiveSet(0);
+ }
+ outlineGeom->getOrCreateStateSet()->setMode(GL_BLEND,osg::StateAttribute::OFF);
+ outlineGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,
+ osg::PolygonMode::LINE),
+ osg::StateAttribute::ON);
+ outlineGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::PolygonOffset(-(offset+1), -(offset+1)),
+ osg::StateAttribute::ON);
+ outlineGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(lineWidth),
+ osg::StateAttribute::ON);
+ color = new osg::Vec4Array;
+ color->push_back(lineColor);
+ if((*color)[0][3] < 1.0)
+ {
+ outlineGeom->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
+ outlineGeom->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
+ }
+ outlineGeom->setColorArray(color.get());
+ outlineGeom->setCullCallback(new osg::ClusterCullingCallback(osg::Vec3d(0.0,0.0,0.0),
+ localNormal,
+ 0.0));
+ geometryNode->addDrawable(outlineGeom.get());
+ outlineGeom->setSupportsDisplayList(true);
+ outlineGeom->setUseDisplayList(true);
+ }
+#endif
+ if(needsReTessFlag)
+ {
+ osgUtil::Tessellator tes;
+
+ tes.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS);
+ tes.setBoundaryOnly(false);
+ tes.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD);
+ tes.retessellatePolygons(*kmlPrimitiveGeom);
+ }
+
+#if 0
+ if(computeNormals)
+ {
+// if(outlineGeom.valid())
+ {
+ osgUtil::SmoothingVisitor sv;
+ sv.smooth(*kmlPrimitiveGeom);
+// FaceNormalVisitor sv;
+// sv.createFaceNormals(*kmlPrimitiveGeom); // this will replace the normal vector with a new one
+ kmlPrimitiveGeom->getOrCreateStateSet()->setMode(GL_LIGHTING,
+ osg::StateAttribute::ON);
+ kmlPrimitiveGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::ShadeModel(osg::ShadeModel::FLAT),
+ osg::StateAttribute::ON);
+ }
+ }
+#endif
+ if(theLod.valid()) // only do a custom draw if we need to
+ {
+ theDraw = new ossimPlanetKmlPlacemarkNode::PlacemarkGeometryDraw;
+ kmlPrimitiveGeom->setDrawCallback(theDraw.get());
+ }
+ if(outlineGeom.valid())
+ {
+ outlineGeom->setDrawCallback(theDraw.get());
+ }
+ if(kmlPrimitiveGeom->getNumPrimitiveSets() > 0)
+ {
+ geometryNode->addDrawable(kmlPrimitiveGeom.get());
+ }
+ if(geometryNode->getNumDrawables()> 0)
+ {
+ localToWorldTransform->addChild(geometryNode.get());
+ }
+ theKmlGeometries->addChild(localToWorldTransform.get());
+ } // end for loop for each geomtry primitive
+ osg::BoundingSphere bs = theKmlGeometries->getBound();
+ theRadius = bs.radius();
+ theCenter = bs.center();
+ osg::Vec3d tempLlh;
+ landModel->inverse(theCenter, tempLlh);
+ tempLlh[2] = 0.0;
+ landModel->forward(tempLlh, theCenter);
+
+// std::cout << "<" << tempLlh[0] << ", " << tempLlh[1] << ", " << tempLlh[2] << std::endl;
+// osgUtil::TriStripVisitor tsv;
+// tsv.setMinStripSize(3);
+// tsv.stripify(*kmlPrimitiveGeom);
+ // Now add the geometry
+// theKmlGeometries->addChild(theGeometry.get());
+
+ return true;
+}
+
+double ossimPlanetKmlPlacemarkNode::convertHeight(const osg::Vec3d& kmlWorldPoint,
+ ossimPlanetAltitudeMode altMode,
+ ossimPlanetGeoRefModel* landModel)const
+{
+ osg::Vec3d worldPoint(kmlWorldPoint[1],
+ kmlWorldPoint[0],
+ kmlWorldPoint[2]);
+ switch(altMode)
+ {
+ case ossimPlanetAltitudeMode_CLAMP_TO_GROUND:
+ {
+ // note KML is lon then lat so let's reverse
+ return landModel->getHeightAboveEllipsoid(kmlWorldPoint[1],
+ kmlWorldPoint[0]);
+ break;
+ }
+ case ossimPlanetAltitudeMode_RELATIVE_TO_GROUND:
+ {
+ return kmlWorldPoint[2] + landModel->getHeightAboveEllipsoid(kmlWorldPoint[1],
+ kmlWorldPoint[0]);
+ break;
+ }
+ default:
+ {
+ return kmlWorldPoint[2] + landModel->getGeoidOffset(kmlWorldPoint[1],
+ kmlWorldPoint[0]);
+ break;
+ }
+ }
+
+ return 0.0;
+}
+
+void ossimPlanetKmlPlacemarkNode::convertPointsToLocalCoordinates(osg::Vec3Array* result,
+ const ossimPlanetKmlGeometry::PointListType& pointList,
+ const osg::Matrixd& worldToLocalTransform,
+ ossimPlanetGeoRefModel* landModel,
+ ossimPlanetAltitudeMode altMode,
+ double& minHeight,
+ double& maxHeight)const
+{
+ minHeight = 99999999.0;
+ maxHeight = -99999999.0;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = pointList.size();
+ osg::Vec3d xyz;
+ osg::Vec3d localPoint;
+ for(idx = 0; idx < upper; ++idx)
+ {
+ osg::Vec3d worldPoint(pointList[idx][1],
+ pointList[idx][0],
+ convertHeight(pointList[idx],
+ altMode,
+ landModel));
+ if(worldPoint[2] < minHeight) minHeight = worldPoint[2];
+ if(worldPoint[2] > maxHeight) maxHeight = worldPoint[2];
+ landModel->forward(worldPoint, xyz);
+ localPoint = xyz*worldToLocalTransform;
+ result->push_back(localPoint);
+ }
+}
+
+// void ossimPlanetKmlPlacemarkNode::extrude(osg::ref_ptr<osg::Geometry> result,
+// osg::Vec3Array* verts,
+// bool polygonFlag)const
+// {
+// if(verts->size() > 1)
+// {
+// ossim_uint32 topSequenceMaxIdx = verts->size()/2; // top layer
+// ossim_uint32 startTopIdx = 0;
+// ossim_uint32 startBottomIdx = topSequenceMaxIdx;
+// ossim_uint32 idx = 0;
+// ossim_uint32 idxMax = verts->size();
+
+// // lt's do the wall first
+// osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP, idxMax));
+
+// for(idx = 0; idx < idxMax; ++idx)
+// {
+// if((idx%2)==0) // do top
+// {
+// drawElements[idx] = startTopIdx;
+// ++startTopIdx;
+// }
+// else // do bottom
+// {
+// drawElements[idx] = startBottomIdx;
+// ++startBottomIdx;
+// }
+// }
+// result->addPrimitiveSet(&drawElements);
+// if(polygonFlag)
+// {
+// osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_POLYGON, topSequenceMaxIdx));
+// for(idx = 0; idx < topSequenceMaxIdx; ++idx)
+// {
+// drawElements[idx] = idx;
+// }
+// result->addPrimitiveSet(&drawElements);
+// }
+// result->setSupportsDisplayList(true);
+// }
+// else
+// {
+// result->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, verts->size()));
+// }
+// }
+void ossimPlanetKmlPlacemarkNode::extrude(osg::ref_ptr<osg::Geometry> result,
+ osg::Vec3Array* verts,
+ osg::Vec3Array* extrusionVerts,
+ const std::vector<std::pair<ossim_uint32, ossim_uint32> >& extrusionGroups)const
+{
+ if(verts->size() == 1)
+ {
+ verts->insert(verts->end(),
+ extrusionVerts->begin(),
+ extrusionVerts->end());
+ result->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, verts->size()));
+ }
+ else
+ {
+ ossim_uint32 offsetIdx = verts->size();
+ ossim_uint32 extrusionIdx = 0;
+ // create walls for geometry
+ verts->insert(verts->end(),
+ extrusionVerts->begin(),
+ extrusionVerts->end());
+ for(extrusionIdx = 0; extrusionIdx<extrusionGroups.size();++extrusionIdx)
+ {
+ ossim_uint32 startIdx = extrusionGroups[extrusionIdx].first;
+ ossim_uint32 startTopIdx = startIdx;
+ ossim_uint32 startBottomIdx = startTopIdx + offsetIdx;
+ ossim_uint32 idx = 0;
+ ossim_uint32 idxMax = extrusionGroups[extrusionIdx].second*2;
+ // makeWalls
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP, idxMax));
+ for(idx = 0;idx < idxMax;++idx)
+ {
+ if((idx%2)==0)
+ {
+ drawElements[idx] = startTopIdx;
+ ++startTopIdx;
+ // do top point
+ }
+ else
+ {
+ drawElements[idx] = startBottomIdx;
+ ++startBottomIdx;
+ // do bottom point
+ }
+ }
+ result->addPrimitiveSet(&drawElements);
+ }
+ }
+
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetKmlScreenOverlayNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlScreenOverlayNode.cpp
new file mode 100644
index 0000000..422384d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetKmlScreenOverlayNode.cpp
@@ -0,0 +1,359 @@
+#include <ossimPlanet/ossimPlanetKmlScreenOverlayNode.h>
+#include <osg/Projection>
+#include <osg/Geode>
+#include <osg/MatrixTransform>
+#include <osg/Matrixd>
+#include <osgUtil/CullVisitor>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <osgUtil/IntersectVisitor>
+
+ossimPlanetKmlScreenOverlayNode::ossimPlanetKmlScreenOverlayNode(ossimPlanetKmlLayer* layer,
+ ossimPlanetKmlObject* obj)
+ :ossimPlanetKmlLayerNode(layer, obj)
+{
+ theCameraNode = new osg::CameraNode;
+ theGroup = new osg::Group;
+ theCameraNode->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ theCameraNode->setViewMatrix(osg::Matrix::identity());
+ theCameraNode->setClearMask(GL_DEPTH_BUFFER_BIT);
+ theCameraNode->setRenderOrder(osg::CameraNode::POST_RENDER);
+ theGroup->addChild(theCameraNode.get());
+ theViewportChangedFlag = false;
+ theNeedsUpdateFlag = false;
+ osg::StateSet* stateset = theCameraNode->getOrCreateStateSet();
+ stateset->setMode(GL_LIGHTING,
+ osg::StateAttribute::OFF);
+// stateset->setMode(GL_COLOR_MATERIAL,
+// osg::StateAttribute::OFF);
+ stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+// stateset->setRenderBinDetails(12,"RenderBin");
+ stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+ stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+}
+
+void ossimPlanetKmlScreenOverlayNode::traverse(osg::NodeVisitor& nv)
+{
+ if(!enableFlag()) return;
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(theViewport.valid()&&theViewportChangedFlag)
+ {
+ theCameraNode->setProjectionMatrix(osg::Matrix::ortho2D(theViewport->x(),
+ theViewport->width(),
+ theViewport->y(),
+ theViewport->height()));
+ theViewportChangedFlag = false;
+ update();
+ }
+
+ if(theNeedsUpdateFlag)
+ {
+ update();
+ }
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(cullVisitor)
+ {
+ double x = cullVisitor->getViewport()->x();
+ double y = (int)cullVisitor->getViewport()->y();
+ double w = (int)cullVisitor->getViewport()->width();
+ double h = (int)cullVisitor->getViewport()->height();
+ if(!theViewport.valid())
+ {
+ theViewport = new osg::Viewport(x,y,w,h);
+ theViewportChangedFlag = true;
+ }
+ else
+ {
+ if( !ossim::almostEqual(theViewport->x(), x)||
+ !ossim::almostEqual(theViewport->y(), y)||
+ !ossim::almostEqual(theViewport->width(), w)||
+ !ossim::almostEqual(theViewport->height(), h))
+ {
+ theViewport->setViewport(x,y,w,h);
+ theViewportChangedFlag = true;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if(dynamic_cast<osgUtil::IntersectVisitor*>(&nv))
+ {
+ return;
+ }
+ break;
+ }
+ }
+ // if the viewport is valid and we have been setup to draw for the current viewport
+ //
+ if(theViewport.valid())
+ {
+ theGroup->accept(nv);
+ }
+}
+
+bool ossimPlanetKmlScreenOverlayNode::init()
+{
+ osg::ref_ptr<ossimPlanetKmlScreenOverlay> overlay = dynamic_cast<ossimPlanetKmlScreenOverlay*> (theKmlObject.get());
+ if(!overlay.valid()) return false;
+ theViewportChangedFlag = true;
+ theOverlayOrigin[0] = overlay->overlayX();
+ theOverlayOrigin[1] = overlay->overlayY();
+ theOverlayXUnits = overlay->overlayXUnits();
+ theOverlayYUnits = overlay->overlayYUnits();
+ theScreenOrigin[0] = overlay->screenX();
+ theScreenOrigin[1] = overlay->screenY();
+ theScreenXUnits = overlay->screenXUnits();
+ theScreenYUnits = overlay->screenYUnits();
+ theRotationOrigin[0] = overlay->rotationX();
+ theRotationOrigin[1] = overlay->rotationY();
+ theRotationXUnits = overlay->rotationXUnits();
+ theRotationYUnits = overlay->rotationYUnits();
+ theSize[0] = overlay->sizeX();
+ theSize[1] = overlay->sizeY();
+ theSizeXUnits = overlay->sizeXUnits();
+ theSizeYUnits = overlay->sizeYUnits();
+ theRotation = overlay->rotation();
+
+ if(overlay->icon().valid())
+ {
+// std::cout << "Downoading overlay image" << std::endl;
+ ossimFilename file = overlay->icon()->download();
+// std::cout << "file = " << file << std::endl;
+ if(file.exists())
+ {
+ theIconGeode = new osg::Geode;
+
+ theIconGeom = theLayer->getOrCreateIconEntry(file);
+ theIconGeom->setGeometry(osg::Vec3d(0.0,0.0,0.0),
+ osg::Vec3d(0.0, 0.0, 0.0),
+ osg::Vec3d(0.0, 0.0, 0.0));
+ theIconGeode->addDrawable(theIconGeom.get());
+ theCameraNode->addChild(theIconGeode.get());
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return overlay->icon().valid();
+}
+
+void ossimPlanetKmlScreenOverlayNode::update()
+{
+ if((!theIconGeom.valid())||(!theIconGeom->texture().valid())) return;
+ if(theIconGeom->texture()->getImage())
+ {
+ ossim_uint32 w = theIconGeom->texture()->getImage()->s();
+ ossim_uint32 h = theIconGeom->texture()->getImage()->t();
+ if(w||h)
+ {
+ osg::Vec3d screenOrigin;
+ osg::Vec3d overlayOrigin;
+ osg::Vec3d size;
+ computeScreenXY(screenOrigin);
+ computeOverlayXY(overlayOrigin);
+ computeSize(size);
+// std::cout << "oringx = " << origin[0] << std::endl;
+// std::cout << "oringy = " << origin[1] << std::endl;
+ theIconGeom->setGeometry(screenOrigin-overlayOrigin,
+ osg::Vec3d(size[0], 0.0, 0.0),
+ osg::Vec3d(0.0, size[1], 0.0));
+// std::cout << "W = " << theIconGeom->texture()->getImage()->s() << std::endl;
+ theNeedsUpdateFlag = false;
+ }
+ else
+ {
+ theNeedsUpdateFlag = true;
+ }
+ }
+ else
+ {
+ theNeedsUpdateFlag = true;
+// std::cout << "NOT VALID!!!" << std::endl;
+ }
+}
+
+void ossimPlanetKmlScreenOverlayNode::computeOverlayXY(osg::Vec3d& position)
+{
+ osg::Vec3d size;
+ computeSize(size);
+ switch(theOverlayXUnits)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ position[0] = theOverlayOrigin[0]*size[0];
+ break;
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ position[0] = theOverlayOrigin[0];
+ break;
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ switch(theScreenYUnits)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ position[1] = theOverlayOrigin[1]*size[1];
+
+ break;
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ position[1] = theOverlayOrigin[1];
+ break;
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void ossimPlanetKmlScreenOverlayNode::computeScreenXY(osg::Vec3d& position)
+{
+ switch(theScreenXUnits)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ position[0] = theViewport->x() + theScreenOrigin[0]*theViewport->width();
+ break;
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ position[0] = theViewport->x() + theScreenOrigin[0];
+ break;
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ switch(theScreenYUnits)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ position[1] = theViewport->y() + theScreenOrigin[1]*theViewport->height();
+
+ break;
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ position[1] = theViewport->y() + theScreenOrigin[1];
+ break;
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void ossimPlanetKmlScreenOverlayNode::computeSize(osg::Vec3d& size)
+{
+ ossim_uint32 iw = (ossim_uint32)theIconGeom->texture()->getImage()->s();
+ ossim_uint32 ih = (ossim_uint32)theIconGeom->texture()->getImage()->t();
+ ossim_uint32 vw = (ossim_uint32)theViewport->width();
+ ossim_uint32 vh = (ossim_uint32)theViewport->height();
+ if(theSize[0] < 0)
+ {
+ size[0] = iw;
+ }
+ else if(theSize[0] > 0)
+ {
+ switch(theSizeXUnits)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ size[0] = theSize[0]*vw;
+ break;
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ size[0] = theSize[0];
+ break;
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ if(theSize[1] < 0)
+ {
+ size[1] = ih;
+ }
+ else if(theSize[1] > 0)
+ {
+ switch(theSizeXUnits)
+ {
+ case ossimPlanetKmlUnits_FRACTION:
+ {
+ size[1] = theSize[1]*vh;
+ break;
+ }
+ case ossimPlanetKmlUnits_PIXELS:
+ {
+ size[1] = theSize[1];
+ break;
+ }
+ case ossimPlanetKmlUnits_INSET_PIXELS:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ if(theSize[0] == 0 && theSize[1] == 0)
+ {
+ size[0] = iw;
+ size[1] = ih;
+ }
+ else if(theSize[0] == 0)
+ {
+ double scale = (double)size[1]/(double)ih;
+ size[0] = scale*iw;
+ }
+ else if(theSize[1] == 0)
+ {
+ double scale = (double)size[0]/(double)iw;
+ size[1] = scale*ih;
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLabelGeom.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLabelGeom.cpp
new file mode 100644
index 0000000..47d5e61
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLabelGeom.cpp
@@ -0,0 +1,166 @@
+#include <ossimPlanet/ossimPlanetLabelGeom.h>
+#include <osgUtil/CullVisitor>
+
+ossimPlanetLabelGeom::ossimPlanetLabelGeom(const ossimString& label,
+ double characterSizeInObjectSpace)
+{
+ theColor = osg::Vec4f(1.0f,1.0f, 1.0f, 1.0f);
+ theLabel = new osgText::Text;
+ theLabel->setAxisAlignment(osgText::Text:: XZ_PLANE);
+ theLabel->setColor(theColor);
+ theLabel->setCharacterSize(characterSizeInObjectSpace);
+ theLabel->setLayout(osgText::Text::LEFT_TO_RIGHT);
+ theLabel->setPosition(osg::Vec3d(0.0,0.0,0.0));
+ theLabel->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
+ theLabel->setAlignment(osgText::Text:: CENTER_BOTTOM);
+ theLabel->setMaximumWidth(-1.0);
+ theLabel->setMaximumHeight(-1.0);
+ theLabel->setText(label);
+ theBillboard = new osg::Billboard;
+ theBillboard->addDrawable(theLabel.get());
+ theBillboard->setMode(osg::Billboard::POINT_ROT_WORLD);
+ theTransform = new osg::MatrixTransform;
+ theShowState = ossimPlanetLabelGeom::SHOW_WHEN_FULL_RES;
+ theShowFlag = true;
+ theEnableFlag = true;
+ theTransform->addChild(theBillboard.get());
+
+
+ setUpdateCallback(new ossimPlanetLabelGeomUpdateCallback());
+ dirtyBound();
+}
+
+ossimPlanetLabelGeom::~ossimPlanetLabelGeom()
+{
+ theLabel = 0;
+ theBillboard = 0;
+ theTransform = 0;
+}
+
+void ossimPlanetLabelGeom::setAlignment(osgText::Text::AlignmentType alignment)
+{
+ theLabel->setAlignment(alignment);
+ dirtyBound();
+}
+
+void ossimPlanetLabelGeom::setCharacterSizeInObjectSpace(double objectSize)
+{
+ theLabel->setCharacterSize(objectSize);
+ dirtyBound();
+}
+
+osg::ref_ptr<osgText::Text> ossimPlanetLabelGeom::getLabel()
+{
+ return theLabel.get();
+}
+
+void ossimPlanetLabelGeom::setLabel(const ossimString& label)
+{
+ theLabel->setText(label);
+ dirtyBound();
+}
+/**
+ * Setting to 0 or negative says there is no max height.
+ */
+void ossimPlanetLabelGeom::setMaxHeightInPixels(double pixelHeight)
+{
+ theMaxHeightInPixels = pixelHeight;
+ dirtyBound();
+}
+/**
+ * Setting to 0 or negative value says there is no minimum height.
+ */
+void ossimPlanetLabelGeom::setMinHeightInPixels(double pixelHeight)
+{
+ theMinHeightInPixels = pixelHeight;
+ dirtyBound();
+}
+
+void ossimPlanetLabelGeom::setColor(float r, float g, float b, float a)
+{
+ theColor[0] = r;
+ theColor[1] = g;
+ theColor[2] = b;
+ theColor[3] = a;
+
+ theLabel->setColor(theColor);
+}
+
+void ossimPlanetLabelGeom::setEnableFlag(bool enableFlag)
+{
+ theEnableFlag = enableFlag;
+}
+
+void ossimPlanetLabelGeom::setShowFlag(bool show)
+{
+ theShowFlag = show;
+}
+
+void ossimPlanetLabelGeom::traverse(osg::NodeVisitor& nv)
+{
+ if(!theEnableFlag) return;
+
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(theUpdateTransformFlag)
+ {
+ theTransform->setMatrix(theMatrix);
+ dirtyBound();
+ theUpdateTransformFlag = false;
+ }
+ theTransform->accept(nv);
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osgUtil::CullVisitor* cullVisitor = (osgUtil::CullVisitor*)(&nv);
+ double pixelSize = cullVisitor->pixelSize(osg::Vec3d(0.0,0.0,0.0), theLabel->getCharacterHeight());
+ if(theMaxHeightInPixels > 0.0)
+ {
+ if(pixelSize > theMaxHeightInPixels)
+ {
+ theUpdateTransformFlag = true;
+ double scale = theMaxHeightInPixels/pixelSize;
+ theMatrix = osg::Matrixd::scale(osg::Vec3d(scale, scale, scale));
+ if(theShowState == ossimPlanetLabelGeom::SHOW_WHEN_FULL_RES)
+ {
+ theShowFlag = true;
+ }
+ }
+ else if(theShowState == ossimPlanetLabelGeom::SHOW_WHEN_FULL_RES)
+ {
+ theShowFlag = false;
+ }
+ }
+ else
+ {
+ if((theMinHeightInPixels > 0.0)&&
+ (pixelSize < theMinHeightInPixels))
+ {
+ theUpdateTransformFlag = true;
+ double scale = theMinHeightInPixels/pixelSize;
+ theMatrix = osg::Matrixd::scale(osg::Vec3d(scale, scale, scale));
+ }
+
+ theShowFlag = true;
+ }
+ if(theShowFlag)
+ {
+ theTransform->accept(nv);
+ }
+ break;
+ }
+ default:
+ {
+ theTransform->accept(nv);
+ break;
+ }
+ }
+}
+
+osg::BoundingSphere ossimPlanetLabelGeom::computeBound() const
+{
+ return theTransform->getBound();
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLand.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLand.cpp
new file mode 100644
index 0000000..296d362
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLand.cpp
@@ -0,0 +1,1695 @@
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <osgUtil/CullVisitor>
+#include <osgDB/DatabasePager>
+#include <osgDB/Registry>
+#include <osgGA/EventVisitor>
+#include <ossimPlanet/ossimPlanetGridUtility.h>
+#include <ossimPlanet/ossimPlanetPagedLandLod.h>
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <ossimPlanet/ossimPlanetLandReaderWriter.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossim/base/ossimFilename.h>
+#include <iostream>
+#include <osg/GL2Extensions>
+#include <ossimPlanet/ossimPlanetSrtmElevationDatabase.h>
+#include <ossim/elevation/ossimElevSourceFactory.h>
+#include <ossimPlanet/ossimPlanetElevationRegistry.h>
+#include <ossimPlanet/ossimPlanetSrtmElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetDtedElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetGeneralRasterElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+
+class ossimPlanetLandUpdateCallback : public osg::NodeCallback
+{
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ ossimPlanetLand* n = dynamic_cast<ossimPlanetLand*>(node);
+ if(n)
+ {
+ n->traverse(*nv);
+
+ return;
+ }
+ }
+};
+
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static ossim_uint32 allocated = 0;
+#endif
+
+class ossimPlanetLandRefreshVisitor : public osg::NodeVisitor
+{
+public:
+ ossimPlanetLandRefreshVisitor(ossimPlanetLand* land)
+ :osg::NodeVisitor(NODE_VISITOR,
+ TRAVERSE_ALL_CHILDREN),
+ theLand(land)
+ {
+ theGrid = theLand->theReaderWriter->gridUtility();
+ theW = theGrid->getTileWidth();
+ theH = theGrid->getTileHeight();
+ }
+ virtual void apply(osg::Group& node)
+ {
+ ossimPlanetPagedLandLod* lod = dynamic_cast<ossimPlanetPagedLandLod*>(&node);
+ if(lod)
+ {
+ double deltaX;
+ double deltaY;
+ theGrid->getWidthHeightInDegrees(deltaX,
+ deltaY,
+ lod->getLevel(),
+ lod->getRow(),
+ lod->getCol());
+ double minLat, minLon, maxLat, maxLon;
+ double deltaLat = deltaY/theH;
+// double deltaLon = deltaX/theW;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ theGrid->getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ lod->getLevel(),
+ lod->getRow(),
+ lod->getCol());
+ osg::ref_ptr<ossimPlanetLand::refreshInfo> info = intersects(minLat, minLon, maxLat, maxLon, gsd.y);
+ if(info.valid())
+ {
+ lod->setRefreshType((ossimPlanetLandRefreshType)(lod->refreshType()|info->theRefreshType));
+ }
+ }
+ osg::NodeVisitor::apply(node);
+ }
+ osg::ref_ptr<ossimPlanetLand::refreshInfo> intersects(double minLat, double minLon, double maxLat, double maxLon,
+ double gsd)const
+ {
+ ossim_uint32 idx = 0;
+ ossim_uint32 size = theLand->theExtentRefreshList.size();
+
+ for(idx = 0; idx < size; ++idx)
+ {
+ if(theLand->theExtentRefreshList[idx]->theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon)&&
+ theLand->theExtentRefreshList[idx]->theExtents->intersectsScale(gsd, gsd))
+ {
+ return theLand->theExtentRefreshList[idx].get();
+ }
+ }
+
+ return 0;
+ }
+protected:
+ ossimPlanetLand* theLand;
+ const ossimPlanetGridUtility* theGrid;
+ ossim_uint32 theW;
+ ossim_uint32 theH;
+};
+
+class ossimPlanetLandTextureCallback : public ossimPlanetTextureLayerCallback
+{
+public:
+ ossimPlanetLandTextureCallback(ossimPlanetLand* land, ossimPlanetLandRefreshType refreshType)
+ :theLand(land),
+ theRefreshType(refreshType)
+ {
+ }
+
+ void setLand(ossimPlanetLand* land)
+ {
+ theLand = land;
+ }
+ virtual void refreshExtent(osg::ref_ptr<ossimPlanetExtents> extent)
+ {
+ if(theLand)
+ {
+ theLand->resetGraph(extent, theRefreshType);
+ }
+ }
+ virtual void layerAdded(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+ {
+ if(theLand)
+ {
+ theLand->resetGraph(layer->getExtents(), theRefreshType);
+ }
+ }
+ virtual void layerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ osg::ref_ptr<ossimPlanetTextureLayer> /*parent*/)
+ {
+ if(theLand)
+ {
+ // only refresh if it was originally enabled
+ if(layer->getEnableFlag())
+ {
+ refreshExtent(layer->getExtents());
+ }
+ }
+ }
+// virtual bool addRequest(osg::ref_ptr<ossimPlanetTextureLayer::TextureRequest> request)
+// {
+// return false;
+// }
+
+protected:
+ ossimPlanetLand* theLand;
+ ossimPlanetLandRefreshType theRefreshType;
+};
+
+ossimPlanetLand::ossimPlanetLand()
+{
+ theShadersInitializedFlag = false;
+// setPathnameAndRegister(":land");
+// ossim_uint64 megaByte = 1024*1024;
+// ossim_uint64 gigaByte = 1024*megaByte;
+// ossim_uint64 maxCacheSize = megaByte*2;
+ theTextureLayerCallback = new ossimPlanetLandTextureCallback(this, ossimPlanetLandRefreshType_TEXTURE);
+ theElevationLayerCallback = new ossimPlanetLandTextureCallback(this, ossimPlanetLandRefreshType_PRUNE);
+ //theLandCache = new ossimPlanetLandCache(maxCacheSize, (ossim_uint64)(maxCacheSize*.85));
+ theCurrentShaderProgram = new ossimPlanetShaderProgramSetup();
+ theLandCache = new ossimPlanetLandCache(0,0);
+ theReferenceLayer = new ossimPlanetTextureLayerGroup;
+ theOverlayLayers = new ossimPlanetTextureLayerGroup;
+ theReferenceLayer->setName("Reference");
+ theOverlayLayers->setName("Overlay");
+ theReaderWriter = new ossimPlanetLandReaderWriter();
+ theReaderWriter->setMultiTextureEnableFlag(false);
+ theReaderWriter->setReferenceLayer(theReferenceLayer.get());
+ theReaderWriter->setOverlayLayers(theOverlayLayers);
+ theReaderWriter->setLandCache(theLandCache.get());
+ initElevation();
+ theReaderWriter->setElevationDatabase(theElevationDatabase.get());
+// theReaderWriter->setShaderProgram(theCurrentShaderProgram.get());
+ osgDB::Registry::instance()->addReaderWriter(theReaderWriter.get());
+// theGraphResetFlag = true;
+ setUpdateCallback(new ossimPlanetLandUpdateCallback);
+ theCullCallback = new ossimPlanetLandCullCallback();
+ theReaderWriter->setLandNodeCullCallback(theCullCallback.get());
+ theReferenceLayer->addCallback(theTextureLayerCallback);
+ theOverlayLayers->addCallback(theTextureLayerCallback);
+ theElevationDatabase->addCallback( theElevationLayerCallback );
+
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++allocated;
+ std::cout << "ossimPlanetLand count++: " << allocated << std::endl;
+#endif
+}
+
+ossimPlanetLand::~ossimPlanetLand()
+{
+ ((ossimPlanetLandTextureCallback*) theTextureLayerCallback.get())->setLand(0);
+ if(theReferenceLayer.valid())
+ {
+ theReferenceLayer->removeCallback(theTextureLayerCallback);
+ }
+ if(theOverlayLayers.valid())
+ {
+ theOverlayLayers->removeCallback(theTextureLayerCallback);
+ }
+ if( theElevationDatabase.valid())
+ {
+ theElevationDatabase->removeCallback( theTextureLayerCallback );
+ }
+ theStateSet = 0;
+ // OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ osgDB::Registry::instance()->removeReaderWriter(theReaderWriter.get());
+// theNeighborhoodGraph = 0;
+ theReaderWriter = 0;
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ --allocated;
+ std::cout << "ossimPlanetLand count--: " << allocated << std::endl;
+#endif
+}
+
+void ossimPlanetLand::traverse(osg::NodeVisitor& nv)
+{
+// static osg::Timer_t lastTick = osg::Timer::instance()->tick();
+ //OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if((theCurrentShaderProgram.valid())&&(!theGL2Extensions.valid()))//&&
+ //(theCurrentShaderProgram->fragmentType() != ossimPlanetShaderProgramSetup::NO_SHADER))
+ {
+ if(!theStateSet.valid())
+ {
+ theStateSet = getOrCreateStateSet();
+ setStateSet(theStateSet.get());
+ initShaders();
+ }
+ }
+ if(!getNumChildren())
+ {
+ resetGraphLocal();
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRefreshMutex);
+ if(theExtentRefreshList.size())
+ {
+#if 0
+ osgDB::DatabasePager* pager = dynamic_cast<osgDB::DatabasePager*>(nv.getDatabaseRequestHandler());
+
+
+ if(pager)
+ {
+ pager->setAcceptNewDatabaseRequests(false);
+ pager->clear();
+ pager->setDatabasePagerThreadPause(true);
+
+ ossimPlanetLandRefreshVisitor refreshVisitor(this);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < getNumChildren(); ++idx)
+ {
+ getChild(idx)->accept(refreshVisitor);
+ }
+ pager->setAcceptNewDatabaseRequests(true);
+ pager->setDatabasePagerThreadPause(false);
+
+ for(idx = 0; idx < theExtentRefreshList.size(); ++idx)
+ {
+ theLandCache->clearTexturesWithinExtents(theExtentRefreshList[idx]->theExtents.get());
+ }
+ }
+#else
+ osgDB::DatabasePager* pager = dynamic_cast<osgDB::DatabasePager*>(nv.getDatabaseRequestHandler());
+ if(pager)
+ {
+ pager->setAcceptNewDatabaseRequests(false);
+ pager->clear();
+ pager->setDatabasePagerThreadPause(true);
+ }
+ ossimPlanetLandRefreshVisitor refreshVisitor(this);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < getNumChildren(); ++idx)
+ {
+ getChild(idx)->accept(refreshVisitor);
+ }
+ for(idx = 0; idx < theExtentRefreshList.size(); ++idx)
+ {
+ theLandCache->clearTexturesWithinExtents(theExtentRefreshList[idx]->theExtents.get());
+ }
+ if(pager)
+ {
+ pager->setAcceptNewDatabaseRequests(true);
+ pager->setDatabasePagerThreadPause(false);
+ }
+#endif
+ theExtentRefreshList.clear();
+ setRedrawFlag(true);
+ }
+ }
+ ossimPlanetLayer::traverse(nv);
+
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(cullVisitor)
+ {
+ osg::CullSettings::CullingMode mode = cullVisitor->getCullingMode();
+
+ ossimPlanetLayer::traverse(nv);
+
+ cullVisitor->setCullingMode(mode);
+ }
+ else
+ {
+
+ ossimPlanetLayer::traverse(nv);
+ }
+ break;
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+#if 0
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRefreshMutex);
+ if(theRedrawFlag)
+ {
+ osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
+ if(ev)
+ {
+ const osgGA::EventVisitor::EventList& eventList = ev->getEvents();
+ if(eventList.size())
+ {
+ osgGA::EventVisitor::EventList::const_iterator iter = eventList.begin();
+ if(((*iter)->getEventType() == osgGA::GUIEventAdapter::FRAME)&&ev->getActionAdapter())
+ {
+ ev->getActionAdapter()->requestRedraw();
+ theRedrawFlag = false;
+ }
+ }
+ }
+ }
+#endif
+ break;
+ }
+ default:
+ {
+ ossimPlanetLayer::traverse(nv);
+ break;
+ }
+ }
+}
+
+void ossimPlanetLand::setLineOfSiteIntersection(const osg::Vec3d& pt)
+{
+ if(theCullCallback.valid())
+ {
+ theCullCallback->setLineOfSite(pt);
+ }
+}
+
+void ossimPlanetLand::setModel(ossimPlanetGeoRefModel* model)
+{
+ ossimPlanetLayer::setModel(model);
+ resetGraph();
+ theCullCallback = theCullCallback->clone();
+ theReaderWriter->setLandNodeCullCallback(theCullCallback.get());
+ theReaderWriter->setModel(model);
+}
+
+bool ossimPlanetLand::getElevationEnabledFlag()const
+{
+ return theReaderWriter->getElevationEnabledFlag();
+}
+
+void ossimPlanetLand::setElevationEnabledFlag(bool elevationEnabledFlag)
+{
+ resetGraph();
+ theReaderWriter->setElevationEnabledFlag(elevationEnabledFlag);
+}
+
+ossim_float64 ossimPlanetLand::getHeightExag()const
+{
+ return theReaderWriter->getHeightExag();
+}
+
+void ossimPlanetLand::setHeightExag(ossim_float64 heightExag)
+{
+ resetGraph();
+ theReaderWriter->setHeightExag(heightExag);
+}
+
+ossim_uint32 ossimPlanetLand::getElevationPatchSize()const
+{
+ return theReaderWriter->getElevationPatchSize();
+}
+
+void ossimPlanetLand::setElevationPatchSize(ossim_uint32 patchSize)
+{
+ resetGraph();
+ theReaderWriter->setElevationPatchSize(patchSize);
+}
+
+void ossimPlanetLand::setReaderWriter(ossimPlanetLandReaderWriter* /*readerWriter*/)
+{
+}
+
+ossimPlanetLandReaderWriter* ossimPlanetLand::getReaderWriter()
+{
+ return theReaderWriter.get();
+}
+
+const ossimPlanetLandReaderWriter* ossimPlanetLand::getReaderWriter()const
+{
+ return theReaderWriter.get();
+}
+
+ossim_uint32 ossimPlanetLand::getMaxLevelDetail()const
+{
+ return theReaderWriter->getMaxLevelDetail();
+}
+
+void ossimPlanetLand::setMaxLevelDetail(ossim_uint32 maxLevelDetail)
+{
+ resetGraph();
+ theReaderWriter->setMaxLevelDetail(maxLevelDetail);
+}
+
+ossimFilename ossimPlanetLand::getElevationCacheDir()const
+{
+ return theReaderWriter->getElevationCacheDir();
+}
+
+void ossimPlanetLand::setElevationCacheDir(const ossimFilename& cacheDir)
+{
+ resetGraph();
+ theReaderWriter->setElevationCacheDir(cacheDir);
+}
+
+void ossimPlanetLand::resetGraph(const osg::ref_ptr<ossimPlanetExtents> extents,
+ ossimPlanetLandRefreshType refreshType)
+
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRefreshMutex);
+
+ osg::ref_ptr<ossimPlanetLand::refreshInfo> info = new ossimPlanetLand::refreshInfo;
+ info->theRefreshType = refreshType;
+
+ if(extents.valid())
+ {
+ info->theExtents = extents->clone();
+ }
+ else
+ {
+ info->theExtents = new ossimPlanetExtents();
+ }
+ ossim_uint32 idx = 0;
+ bool found = false;
+ for(idx = 0; idx < theExtentRefreshList.size(); ++idx)
+ {
+ if(theExtentRefreshList[idx]->theExtents->equal(info->theExtents))
+ {
+ theExtentRefreshList[idx]->theRefreshType = (ossimPlanetLandRefreshType)(theExtentRefreshList[idx]->theRefreshType |
+ refreshType);
+ found = true;
+ }
+ }
+ if(!found)
+ {
+ theExtentRefreshList.push_back(info);
+ }
+ setRedrawFlag(true);
+}
+
+void ossimPlanetLand::resetGraphLocal()
+{
+ theExtentRefreshList.clear();
+ bool hasPagedLods = false;
+
+ ossim_uint32 idx = 0;
+ for(;((idx < getNumChildren())&&(!hasPagedLods));++idx)
+ {
+ hasPagedLods = (dynamic_cast<ossimPlanetPagedLandLod*>(getChild(idx))!= 0);
+ }
+
+ if(!hasPagedLods)
+ {
+ bool addedChild = false;
+ ossim_uint32 faceCount = theReaderWriter->gridUtility()->getNumberOfFaces();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < faceCount; ++idx)
+ {
+ osg::ref_ptr<osg::Node> node = theReaderWriter->readNode(theReaderWriter->createDbString(0,0,idx), 0).getNode();
+ if(node.valid())
+ {
+ addedChild = true;
+ addChild(node.get());
+ }
+ }
+ }
+ else
+ {
+ for(idx = 0;idx < getNumChildren();++idx)
+ {
+ ossimPlanetPagedLandLod* lod = dynamic_cast<ossimPlanetPagedLandLod*>(getChild(idx));
+ if(lod)
+ {
+ lod->setRefreshType(ossimPlanetLandRefreshType_PRUNE);
+ }
+ }
+ }
+ setRedrawFlag(true);
+}
+
+const osg::ref_ptr<ossimPlanetGeoRefModel> ossimPlanetLand::model()const
+{
+
+ if(theReaderWriter.valid())
+ {
+ return theReaderWriter->model();
+ }
+
+ return 0;
+}
+
+
+void ossimPlanetLand::accept(osg::NodeVisitor& nv)
+{
+ if(nv.validNodeMask(*this))
+ {
+ nv.pushOntoNodePath(this);
+ nv.apply(*this);
+ nv.popFromNodePath();
+ }
+}
+
+bool ossimPlanetLand::addChild( Node *child )
+{
+ setRedrawFlag(true);
+ return Group::addChild(child);
+}
+
+// ossim_uint32 ossimPlanetLand::getNumberOfTextureLayers()const
+// {
+// return theTextureLayers->getNumberOfLayers();
+// }
+
+
+// void ossimPlanetLand::setTextureLayer(osg::ref_ptr<ossimPlanetTextureLayer> textureLayer,
+// ossim_uint32 idx)
+// {
+// ossim_uint32 nLayers = getNumberOfTextureLayers();
+// if(idx == nLayers)
+// {
+// theTextureLayers->addBottom(textureLayer.get());
+// }
+// else if(idx < nLayers)
+// {
+// theTextureLayers->replaceLayer(idx, textureLayer.get());
+// }
+// resetGraph();
+// }
+
+// osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetLand::getTextureLayer(ossim_uint32 idx)
+// {
+// return theTextureLayers->getLayer(idx);
+// }
+
+// const osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetLand::getTextureLayer(ossim_uint32 idx)const
+// {
+// return theTextureLayers->getLayer(idx);
+// }
+
+// osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetLand::removeTextureLayer(ossim_uint32 idx)
+// {
+// return theTextureLayers->removeLayer(idx);
+// }
+
+ossim_uint32 ossimPlanetLand::getNumberOfOverlayLayers()const
+{
+ if(theOverlayLayers.valid())
+ {
+ return theOverlayLayers->numberOfLayers();
+ }
+
+ return 0;
+}
+
+void ossimPlanetLand::setReferenceLayer(osg::ref_ptr<ossimPlanetTextureLayerGroup> reference)
+{
+ if(theReferenceLayer.valid())
+ {
+ theReferenceLayer->removeCallback(theTextureLayerCallback);
+
+ }
+ theReferenceLayer = reference;
+ if(theReaderWriter.valid())
+ {
+ theReaderWriter->setReferenceLayer(theReferenceLayer.get());
+ }
+ if(theReferenceLayer.valid())
+ {
+ theReferenceLayer->addCallback(theTextureLayerCallback);
+ }
+}
+
+osg::ref_ptr<ossimPlanetTextureLayerGroup> ossimPlanetLand::referenceLayer()
+{
+ return theReferenceLayer.get();
+}
+
+const osg::ref_ptr<ossimPlanetTextureLayerGroup> ossimPlanetLand::referenceLayer()const
+{
+ return theReferenceLayer.get();
+}
+
+osg::ref_ptr<ossimPlanetTextureLayerGroup> ossimPlanetLand::overlayLayers()
+{
+ return theOverlayLayers.get();
+}
+
+const osg::ref_ptr<ossimPlanetTextureLayerGroup> ossimPlanetLand::overlayLayers()const
+{
+ return theOverlayLayers.get();
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetLand::overlayLayer(ossim_uint32 layerIdx)
+{
+ if(!theOverlayLayers.valid()) return 0;
+ if(layerIdx < theOverlayLayers->numberOfLayers())
+ {
+ return theOverlayLayers->layer(layerIdx);
+ }
+
+ return 0;
+}
+
+const osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetLand::overlayLayer(ossim_uint32 layerIdx)const
+{
+ if(!theOverlayLayers.valid()) return 0;
+ if(layerIdx < theOverlayLayers->numberOfLayers())
+ {
+ return theOverlayLayers->layer(layerIdx);
+ }
+
+ return 0;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetLand::removeOverlayLayer(ossim_uint32 layerIdx)
+{
+ if(!theOverlayLayers.valid()) return 0;
+ return theOverlayLayers->removeLayer(layerIdx);
+}
+
+void ossimPlanetLand::setCurrentFragmentShaderType(ossimPlanetShaderProgramSetup::ossimPlanetFragmentShaderType fragType)
+{
+ if(!theFragShader.valid()||!theCurrentShaderProgram.valid()) return;
+ if((theCurrentShaderProgram->fragmentType() == ossimPlanetShaderProgramSetup::NO_SHADER)&&
+ (fragType!=ossimPlanetShaderProgramSetup::NO_SHADER))
+ {
+ theReaderWriter->setMultiTextureEnableFlag(true);
+ }
+ switch(fragType)
+ {
+ case ossimPlanetShaderProgramSetup::NO_SHADER:
+ {
+ theReaderWriter->setMultiTextureEnableFlag(false);
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::NO_SHADER);
+ theCurrentShaderProgram->setProgram(theNoShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::TOP:
+ {
+ theFragShader->setShaderSource(theTopSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::TOP);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::REFERENCE:
+ {
+ theFragShader->setShaderSource(theReferenceSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::REFERENCE);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::OPACITY:
+ {
+ theFragShader->setShaderSource(theOpacitySource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::OPACITY);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::HORIZONTAL_SWIPE:
+ {
+ osg::ref_ptr<osg::Uniform> uniformParam = theCurrentShaderProgram->getUniform("swipeType");
+ if(uniformParam.valid())
+ {
+ uniformParam->set((int)0);
+ }
+ theFragShader->setShaderSource(theSwipeSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::HORIZONTAL_SWIPE);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::VERTICAL_SWIPE:
+ {
+ osg::ref_ptr<osg::Uniform> uniformParam = theCurrentShaderProgram->getUniform("swipeType");
+ if(uniformParam.valid())
+ {
+ uniformParam->set((int)1);
+ }
+ theFragShader->setShaderSource(theSwipeSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::VERTICAL_SWIPE);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::BOX_SWIPE:
+ {
+ osg::ref_ptr<osg::Uniform> uniformParam = theCurrentShaderProgram->getUniform("swipeType");
+ if(uniformParam.valid())
+ {
+ uniformParam->set((int)2);
+ }
+ theFragShader->setShaderSource(theSwipeSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::BOX_SWIPE);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::CIRCLE_SWIPE:
+ {
+ osg::ref_ptr<osg::Uniform> uniformParam = theCurrentShaderProgram->getUniform("swipeType");
+ if(uniformParam.valid())
+ {
+ uniformParam->set((int)3);
+ }
+ theFragShader->setShaderSource(theSwipeSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::CIRCLE_SWIPE);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::ABSOLUTE_DIFFERENCE:
+ {
+ theFragShader->setShaderSource(theAbsoluteDifferenceSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::ABSOLUTE_DIFFERENCE);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+
+ break;
+ }
+ case ossimPlanetShaderProgramSetup::FALSE_COLOR_REPLACEMENT:
+ {
+ theFragShader->setShaderSource(theFalseColorReplacementSource);
+ theFragShader->dirtyShader();
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::FALSE_COLOR_REPLACEMENT);
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }// end switch
+ if(!theStateSet.valid())
+ {
+ theStateSet = getOrCreateStateSet();
+ }
+ theStateSet->setAttribute(theCurrentShaderProgram->getProgram());
+ setRedrawFlag(true);
+}
+
+void ossimPlanetLand::setCacheSize(ossim_uint64 maxSize, ossim_uint64 minSize)
+{
+ theLandCache->setCacheSize(maxSize, minSize);
+}
+
+ossim_uint64 ossimPlanetLand::getCacheSize()const
+{
+ return theLandCache->getCacheSize();
+}
+
+
+void ossimPlanetLand::setSplitMetricRatio(double ratio)
+{
+ theCullCallback->setSplitMetricRatio(ratio);
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+}
+
+double ossimPlanetLand::getSplitMetricRatio()const
+{
+ return theCullCallback->getSplitMetricRatio();
+
+}
+
+void ossimPlanetLand::setSplitPriorityType(ossimPlanetPriorityType priorityType)
+{
+ theCullCallback->setSplitPriorityType(priorityType);
+}
+
+ossimPlanetPriorityType ossimPlanetLand::getSplitPrioirtyType()const
+{
+ return theCullCallback->getSplitPriorityType();
+}
+
+void ossimPlanetLand::setCullingFlag(bool flag)
+{
+ theCullCallback->setCullingFlag(flag);
+}
+
+bool ossimPlanetLand::getCullingFlag()const
+{
+ return theCullCallback->getCullingFlag();
+}
+
+void ossimPlanetLand::setFreezeRequestFlag(bool flag)
+{
+ theCullCallback->setFreezeRequestFlag(flag);
+}
+
+bool ossimPlanetLand::getFreezRequestFlag()const
+{
+ return theCullCallback->getFreezRequestFlag();
+}
+
+bool ossimPlanetLand::getMipMappingFlag()const
+{
+ return theReaderWriter->getMipMappingFlag();
+}
+
+void ossimPlanetLand::setMipMappingFlag(bool flag)
+{
+ theReaderWriter->setMipMappingFlag(flag);
+ resetGraph(0, ossimPlanetLandRefreshType_TEXTURE);
+}
+
+void ossimPlanetLand::pagedLodAdded(osg::Node* /*parent*/ , osg::Node* /*child*/)
+{
+ setRedrawFlag(true);
+}
+
+void ossimPlanetLand::pagedLodRemoved(osg::Node* /*node*/)
+{
+ setRedrawFlag(true);
+}
+
+void ossimPlanetLand::pagedLodModified(osg::Node* /*node*/)
+{
+ setRedrawFlag(true);
+}
+
+osg::ref_ptr<ossimPlanetShaderProgramSetup> ossimPlanetLand::getCurrentShader()
+{
+ return theCurrentShaderProgram.get();
+}
+
+void ossimPlanetLand::initShaders()
+{
+ theGL2Extensions = new osg::GL2Extensions(0);
+ theShadersInitializedFlag = false;
+ if(!theGL2Extensions->isGlslSupported())
+ {
+ theCurrentShaderProgram = 0;
+ theReaderWriter->setMultiTextureEnableFlag(false);
+ return;
+ }
+ theShadersInitializedFlag = true;
+ theReaderWriter->setMultiTextureEnableFlag(true);
+ theNoShaderProgram = new osg::Program;
+
+ theCurrentShaderProgram = new ossimPlanetShaderProgramSetup;
+ theLandShaderProgram = new osg::Program;
+ theCurrentShaderProgram->setProgram(theLandShaderProgram.get());
+ ossimFilename file = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ ossimFilename shaders = file.dirCat("planet");
+ shaders = shaders.dirCat("shaders");
+ if(!shaders.exists())
+ {
+ shaders = ossimEnvironmentUtility::instance()->getInstalledOssimSupportDir();
+ shaders = shaders.dirCat("planet");
+ shaders = shaders.dirCat("shaders");
+ }
+ bool vertexShaderExists = false;
+ if(shaders.exists())
+ {
+ ossimFilename vertShader = shaders.dirCat("land.vert");
+ if(vertShader.exists())
+ {
+ std::vector<char> vertBuf(vertShader.fileSize());
+ std::ifstream in(vertShader.c_str());
+
+ in.read(&vertBuf.front(), vertBuf.size());
+ theLandShaderProgram->addShader(new osg::Shader(osg::Shader::VERTEX, &vertBuf.front()));
+ vertexShaderExists = true;
+ }
+ ossimFilename fragFunctions = shaders.dirCat("land.frag");
+ if(fragFunctions.exists())
+ {
+ std::vector<char> buf(fragFunctions.fileSize());
+ std::ifstream in(fragFunctions.c_str());
+
+ in.read(&buf.front(), buf.size());
+ theLandShaderProgram->addShader(new osg::Shader(osg::Shader::FRAGMENT, &buf.front()));
+ }
+ }
+ if(!vertexShaderExists)
+ {
+ char vertexShaderSource[] =
+ "varying vec2 projectedPosition;\n"
+ "varying vec4 position;\n"
+ "varying vec3 normal;\n"
+ "void main(void)\n"
+ "{\n"
+ "\n"
+ " vec4 projPosition = gl_ModelViewProjectionMatrix*gl_Vertex;\n"
+ " projectedPosition = vec2(projPosition[0]/projPosition[2],projPosition[1]/projPosition[2]);\n"
+ " gl_TexCoord[0] = gl_MultiTexCoord0;\n"
+ " gl_Position = ftransform(); \n"
+ " position = gl_Position; \n"
+ " normal = gl_NormalMatrix*gl_Normal; \n"
+ "}\n";
+ theLandShaderProgram->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource));
+ }
+ theFalseColorReplacementSource =
+ "uniform sampler2D referenceTexture; \n"
+ "uniform sampler2D topTexture; \n"
+ "vec4 simpleShader(vec4 color);\n"
+ "void main(void) \n"
+ "{\n"
+ " vec4 color;\n"
+ " vec4 texa = vec4(0.0,0.0,0.0,0.0);\n"
+ " vec4 texb = vec4(0.0,0.0,0.0,0.0);\n"
+ " float weight = 0.0;\n"
+ " texa = texture2D(referenceTexture, gl_TexCoord[0].st);\n"
+ " texb = texture2D(topTexture, gl_TexCoord[0].st);\n"
+ " color[0] = texa[0];\n"
+ " color[1] = 0.0;\n"
+ " color[2] = texb[0];\n"
+ " color[3] = 1.0;\n"
+ " if(texb[3] < .000001)\n"
+ " {\n"
+ " color = texa;\n"
+ " }\n"
+ " gl_FragColor = (color);\n"
+ "}\n";
+ theAbsoluteDifferenceSource =
+ "uniform sampler2D referenceTexture; \n"
+ "uniform sampler2D topTexture; \n"
+ "\n"
+ "void main(void) \n"
+ "{\n"
+ " vec4 color;\n"
+ " vec4 texa = vec4(0.0,0.0,0.0,0.0);\n"
+ " vec4 texb = vec4(0.0,0.0,0.0,0.0);\n"
+ " texa = texture2D(referenceTexture, gl_TexCoord[0].st);\n"
+ " texb = texture2D(topTexture, gl_TexCoord[0].st);\n"
+ " color = texa-texb;\n"
+ " if(texb[3] > .000001)\n"
+ " {\n"
+ " color[0] = abs(color[0]);\n"
+ " color[1] = abs(color[1]);\n"
+ " color[2] = abs(color[2]);\n"
+ " color[3] = 1.0;\n"
+ " }\n"
+ " else\n"
+ " color = texa;\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+ theTopSource =
+ "uniform sampler2D topTexture; \n"
+ "\n"
+ "void main(void) \n"
+ "{\n"
+ " vec4 texa = vec4(0.0,0.0,0.0,0.0);\n"
+ " gl_FragColor = texture2D(topTexture, gl_TexCoord[0].st);\n"
+ "}\n";
+ theReferenceSource =
+ "uniform sampler2D referenceTexture; \n"
+ "\n"
+ "void main(void) \n"
+ "{\n"
+ " vec4 texa = vec4(0.0,0.0,0.0,0.0);\n"
+ " gl_FragColor = texture2D(referenceTexture, gl_TexCoord[0].st);\n"
+ "}\n";
+
+ theOpacitySource =
+ "uniform sampler2D referenceTexture; \n"
+ "uniform sampler2D topTexture; \n"
+ "uniform float param;\n"
+ "\n"
+ "void main(void) \n"
+ "{\n"
+ " vec4 color;\n"
+ " vec4 texa = vec4(0.0,0.0,0.0,0.0);\n"
+ " vec4 texb = vec4(0.0,0.0,0.0,0.0);\n"
+ " texa = texture2D(referenceTexture, gl_TexCoord[0].st);\n"
+ " texb = texture2D(topTexture, gl_TexCoord[0].st);\n"
+ " if(texb[3] > .1)\n"
+ " if(texa[3] > .1)\n"
+ " {\n"
+ " color = mix(texa, texb, param*texb[3]);\n"
+ " color[3] = 1.0;\n"
+ " }\n"
+ " else\n"
+ " color = texb;\n"
+ " else\n"
+ " color = texa;\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+ theSwipeSource =
+ "uniform sampler2D referenceTexture; \n"
+ "uniform sampler2D topTexture; \n"
+ "uniform float param;\n"
+ "uniform int swipeType;\n"
+ "varying vec2 projectedPosition;\n"
+ "\n"
+ "void main(void) \n"
+ "{\n"
+ " vec4 color;\n"
+ " vec4 texa = vec4(0.0,0.0,0.0,0.0);\n"
+ " vec4 texb = vec4(0.0,0.0,0.0,0.0);\n"
+ " float dist;\n"
+ " bool selected = false;\n"
+ " if(swipeType == 0)\n"
+ " {\n"
+ " dist = (1.0 + projectedPosition[0])/2.0;\n"
+ " }\n"
+ " else if(swipeType == 1)\n"
+ " {\n"
+ " dist = (1.0 + projectedPosition[1])/2.0;\n"
+ " }\n"
+ " else if(swipeType == 2)\n"
+ " {\n"
+ " dist = max(abs(projectedPosition[0]), abs(projectedPosition[1]));\n"
+ " }\n"
+ " else \n"
+ " {\n"
+ " dist = length(projectedPosition);\n"
+ " }\n"
+ " texa = texture2D(referenceTexture, gl_TexCoord[0].st);\n"
+ " texb = texture2D(topTexture, gl_TexCoord[0].st);\n"
+ " if(texb[3] > .000001)\n"
+ " if(texa[3] > .000001)\n"
+ " if(dist < abs(param))\n"
+ " color = texa;\n"
+ " else\n"
+ " color = texb;\n"
+ " else\n"
+ " color = texb;\n"
+ " else\n"
+ " color = texa;\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+ osg::ref_ptr<osg::Uniform> param = new osg::Uniform("param",
+ (float)1.0);
+ osg::ref_ptr<osg::Uniform> swipeType = new osg::Uniform("swipeType",
+ 0);
+ theReferenceTexture = new osg::Uniform("referenceTexture",0);
+ theTopTexture = new osg::Uniform("topTexture",1);
+ theFragShader = new osg::Shader(osg::Shader::FRAGMENT, theReferenceSource);
+ theCurrentShaderProgram->addUniform(swipeType.get());
+ theCurrentShaderProgram->addUniform(param.get());
+ theCurrentShaderProgram->addUniform(theReferenceTexture.get());
+ theCurrentShaderProgram->addUniform(theTopTexture.get());
+ theLandShaderProgram->addShader(theFragShader.get());
+ theCurrentShaderProgram->setFragmentType(ossimPlanetShaderProgramSetup::REFERENCE);
+
+
+ theStateSet->addUniform(swipeType.get());
+ theStateSet->addUniform(param.get());
+ theStateSet->addUniform(theReferenceTexture.get());
+ theStateSet->addUniform(theTopTexture.get());
+ theStateSet->setAttribute(theCurrentShaderProgram->getProgram());
+
+ resetGraph();
+
+}
+
+void ossimPlanetLand::initElevation()
+{
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfDatabases = ossimElevManager::instance()->getNumberOfElevationDatabases();
+ theElevationDatabase = new ossimPlanetElevationDatabaseGroup;
+
+ for(idx = 0; idx < numberOfDatabases; ++idx)
+ {
+ const ossimRefPtr<ossimElevationDatabase> database = ossimElevManager::instance()->getElevationDatabase(idx);
+
+ if(database.valid())
+ {
+ ossimFilename directory = ossimFilename(database->getConnectionString());
+ addElevationDirectory(directory, false);
+ }
+ }
+
+ theElevationDatabase->sortByGsd();
+
+}
+
+void ossimPlanetLand::addElevationDirectory(const ossimFilename& file, bool sortFlag)
+{
+ osg::ref_ptr<ossimPlanetElevationDatabase> database = ossimPlanetElevationRegistry::instance()->openDatabase(file);
+ addElevation(database.get(), sortFlag);
+}
+
+void ossimPlanetLand::addElevation(osg::ref_ptr<ossimPlanetElevationDatabase> database, bool sortFlag)
+{
+ if(database.valid())
+ {
+ theElevationDatabase->addBottom(database.get());
+ }
+
+ if(sortFlag)
+ {
+ // make sure the highest accuracy is on top
+ theElevationDatabase->sortByGsd();
+ }
+}
+
+bool ossimPlanetLand::shadersInitialized()const
+{
+ return theShadersInitializedFlag;
+}
+
+void ossimPlanetLand::clearElevation()
+{
+ if(theElevationDatabase->numberOfLayers() > 0)
+ {
+ theElevationDatabase->removeLayers(0, theElevationDatabase->numberOfLayers());
+ }
+}
+
+void ossimPlanetLand::execute(const ossimPlanetAction &a)
+{
+ const ossimPlanetXmlAction* xmlAction = a.toXmlAction();
+
+ if(xmlAction)
+ {
+ xmlExecute(*xmlAction);
+ }
+}
+
+void ossimPlanetLand::xmlExecute(const ossimPlanetXmlAction& a)
+{
+
+ std::string command = a.command();
+ if(a.xmlNode().valid())
+ {
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ if(command == "Add")
+ {
+ for(idx = 0;idx<children.size();++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ osg::ref_ptr<ossimPlanetTextureLayer> layer;
+ osg::ref_ptr<ossimPlanetTextureLayer> namedLayer;
+ ossimString parentName = children[idx]->getChildTextValue("Parent/name");
+ ossimString parentId = children[idx]->getChildTextValue("Parent/id");;
+ ossimString description = children[idx]->getChildTextValue("description");
+ ossimString id = children[idx]->getChildTextValue("id");
+ ossimString name = children[idx]->getChildTextValue("name");
+ ossimString groupType = children[idx]->getAttributeValue("groupType");
+ if(!id.empty()&&referenceLayer().valid())
+ {
+ namedLayer = referenceLayer()->findLayerByNameAndId("", id);
+ if(namedLayer.valid())
+ {
+ // do not do duplicate named ID's
+ return;
+ }
+ }
+ if(tag == "Image")
+ {
+ ossimFilename filename = children[idx]->getChildTextValue("filename");
+ layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(filename);
+ }
+ else if(groupType == "groundTexture")
+ {
+ layer = new ossimPlanetTextureLayerGroup;
+ }
+ if(layer.valid()&&referenceLayer().valid())
+ {
+ if(!parentName.empty()&&!parentId.empty())
+ {
+ namedLayer = referenceLayer()->findLayerByNameAndId(parentName, parentId);
+ }
+ else if(!parentName.empty())
+ {
+ namedLayer = referenceLayer()->findLayerByName(parentName);
+ }
+ else if(!parentId.empty())
+ {
+ namedLayer = referenceLayer()->findLayerById(parentId);
+ }
+
+ layer->setName(name);
+ layer->setId(id);
+ layer->setDescription(description);
+
+ if(namedLayer.valid()&&namedLayer->asGroup())
+ {
+ ossimPlanetTextureLayerGroup* group = namedLayer->asGroup();
+ group->addTop(layer.get());
+ }
+ else
+ {
+ referenceLayer()->addTop(layer.get());
+ }
+ }
+ }
+ }
+ else if(command == "Remove")
+ {
+ ossimString id;
+ ossimString name;
+ ossimString parentId;
+ if(children.size() > 0)
+ {
+ for(idx = 0;idx<children.size();++idx)
+ {
+ parentId = children[idx]->getAttributeValue("parentId");;
+ id = children[idx]->getAttributeValue("id");
+ name = children[idx]->getAttributeValue("name");
+
+ if(id.empty() && name.empty())
+ {
+ id = children[idx]->getChildTextValue("id");
+ name = children[idx]->getChildTextValue("name");
+ }
+ if(!id.empty()||
+ !name.empty())
+ {
+ ossimPlanetTextureLayer* parent = 0;
+ if(!parentId.empty())
+ {
+ parent = referenceLayer()->findLayerById(parentId);
+ }
+ else
+ {
+ parent = referenceLayer().get();
+ }
+ ossimPlanetTextureLayer* layerToRemove = 0;
+ if(parent)
+ {
+ if(!name.empty()&&!id.empty())
+ {
+ layerToRemove = parent->findLayerByNameAndId(name, id);
+ }
+ else if(!name.empty())
+ {
+ layerToRemove = parent->findLayerByName(name);
+ }
+ else if(!id.empty())
+ {
+ layerToRemove = parent->findLayerById(id);
+ }
+ }
+ if(layerToRemove)
+ {
+ layerToRemove->remove();
+ }
+ }
+
+ }
+ }
+ else
+ {
+ id = a.xmlNode()->getAttributeValue("id");
+ name = a.xmlNode()->getAttributeValue("name");
+ ossimPlanetTextureLayer* layerToRemove = 0;
+ if(!name.empty()&&!id.empty())
+ {
+ layerToRemove = referenceLayer()->findLayerByNameAndId(name, id);
+ }
+ else if(!name.empty())
+ {
+ layerToRemove = referenceLayer()->findLayerByName(name);
+ }
+ else if(!id.empty())
+ {
+ layerToRemove = referenceLayer()->findLayerById(id);
+ }
+
+ if(layerToRemove)
+ {
+ layerToRemove->remove();
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetLand::addImageObject(const ossimString& /*type*/, const ossimString& /*arg*/)
+{
+#if 0
+ ossimString name;
+ ossimString id;
+ ossimString description;
+ ossimString parentName;
+ ossimString parentId;
+ ossimString objectName;
+ ossimString objectArg;
+ ossim_uint32 idx;
+ if(type == "Image")
+ {
+ ossimString filename;
+ ossimPlanetAction nestedAction(": dummy " + arg);
+ for(idx = 1; idx <= nestedAction.argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ nestedAction.arg(idx)))
+ {
+ if(objectName == "Description")
+ {
+ description = objectArg;
+ }
+ else if(objectName == "Name")
+ {
+ name = objectArg;
+ }
+ else if(objectName == "Id")
+ {
+ id = objectArg;
+ }
+ else if(objectName == "Filename")
+ {
+ filename = objectArg;
+ }
+ else if(objectName == "Parent")
+ {
+ ossimString objectName2;
+ ossimString objectArg2;
+ ossimPlanetAction nestedParentAction(": dummy " + objectArg);
+ ossim_uint32 idx2;
+ for(idx2 = 1; idx2 <= nestedParentAction.argCount(); ++idx2)
+ {
+ if(mkUtils::extractObjectAndArg(objectName2,
+ objectArg2,
+ nestedAction.arg(idx)))
+ {
+ if(objectName == "Name")
+ {
+ parentName = objectArg;
+ }
+ else if(objectName == "Id")
+ {
+ parentId = objectArg;
+ }
+ }
+ }// end Parent object for loop
+ }
+ }
+ } // end Image object for loop
+ if(ossimFilename(filename).exists())
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(filename.c_str());
+
+ if(layer.valid())
+ {
+ if(layer->isStateSet(ossimPlanetTextureLayer_NO_SOURCE_DATA)||
+ layer->isStateSet(ossimPlanetTextureLayer_NO_GEOM))
+ {
+ // will need to notify later.
+ layer = 0;
+ return;
+ }
+ if(!description.empty())
+ {
+ layer->setDescription(description);
+ }
+ if(!name.empty())
+ {
+ layer->setName(name);
+ }
+ if(!id.empty())
+ {
+ layer->setId(id);
+ }
+
+ if(parentName.empty()&&parentId.empty())
+ {
+ referenceLayer()->addTop(layer);
+ }
+ else
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> tempLayer;
+ if(!parentName.empty()&&!parentId.empty())
+ {
+ tempLayer = referenceLayer()->findLayerByNameAndId(parentName, parentId);
+ }
+ else if(!parentName.empty())
+ {
+ tempLayer = referenceLayer()->findLayerByNameAndId(parentName, true);
+ }
+ else if(!parentId.empty())
+ {
+ tempLayer = referenceLayer()->findLayerById(parentName, true);
+ }
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> layerToAddTo = tempLayer.valid()?tempLayer->asGroup():0;
+
+
+ if(layerToAddTo.valid())
+ {
+ layerToAddTo->addTop(layer.get());
+ }
+ else
+ {
+ }
+ }
+ }
+ }
+ }
+ else if(type == "ImageGroup")
+ {
+ ossimPlanetAction nestedAction(": dummy " + arg);
+ for(idx = 1; idx <= nestedAction.argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ nestedAction.arg(idx)))
+ {
+ if(objectName == "Description")
+ {
+ description = objectArg;
+ }
+ else if(objectName == "Name")
+ {
+ name = objectArg;
+ }
+ else if(objectName == "Id")
+ {
+ id = objectArg;
+ }
+ else if(objectName == "Parent")
+ {
+ ossimString objectName2;
+ ossimString objectArg2;
+ ossimPlanetAction nestedParentAction(": dummy " + objectArg);
+ ossim_uint32 idx2;
+ for(idx2 = 1; idx2 <= nestedParentAction.argCount(); ++idx2)
+ {
+ if(mkUtils::extractObjectAndArg(objectName2,
+ objectArg2,
+ nestedAction.arg(idx)))
+ {
+ if(objectName == "Name")
+ {
+ parentName = objectArg;
+ }
+ else if(objectName == "Id")
+ {
+ parentId = objectArg;
+ }
+ }
+ }// end Parent object for loop
+ }
+ }
+ }
+
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> layer = new ossimPlanetTextureLayerGroup;
+ if(!description.empty())
+ {
+ layer->setDescription(description);
+ }
+ if(!name.empty())
+ {
+ layer->setName(name);
+ }
+ if(!id.empty())
+ {
+ layer->setId(id);
+ }
+ if(parentName.empty())
+ {
+ referenceLayer()->addTop(layer.get());
+ }
+ else
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> tempLayer;
+ if(!parentName.empty()&&!parentId.empty())
+ {
+ tempLayer = referenceLayer()->findLayerByNameAndId(parentName, parentId);
+ }
+ else if(!parentName.empty())
+ {
+ tempLayer = referenceLayer()->findLayerByNameAndId(parentName, true);
+ }
+ else if(!parentId.empty())
+ {
+ tempLayer = referenceLayer()->findLayerById(parentName, true);
+ }
+
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> layerToAddTo = tempLayer.valid()?tempLayer->asGroup():0;
+
+ if(layerToAddTo.valid())
+ {
+ layerToAddTo->addTop(layer.get());
+ }
+ else
+ {
+
+ }
+ }
+ }
+#endif
+}
+
+void ossimPlanetLand::add(const ossimPlanetAction& /*a*/)
+{
+#if 0
+ ossimString objectName;
+ ossimString objectArg;
+
+ ossim_uint32 idx = 1;
+ for(idx = 1; idx <= (ossim_uint32)a.argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ a.arg(idx)))
+ {
+ if(objectName == "Image")
+ {
+ addImageObject(objectName, objectArg);
+ }
+ }
+ }
+#endif
+}
+
+void ossimPlanetLand::remove(const ossimPlanetAction& /*a*/)
+{
+#if 0
+ ossimString objectName;
+ ossimString objectArg;
+ ossim_uint32 idx = 1;
+ for(idx = 1; idx <= (ossim_uint32)a.argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ a.arg(idx)))
+ {
+ if((objectName == "Image")||
+ (objectName == "ImageGroup"))
+ {
+ ossimPlanetAction nestedAction(": dummy " + objectArg);
+ ossim_uint32 idx2;
+ ossimString layerName;
+ ossimString id;
+ for(idx2=1; idx2 <= nestedAction.argCount();++idx2)
+ {
+ ossimString tempObjectName;
+ ossimString tempObjectArg;
+ if(mkUtils::extractObjectAndArg(tempObjectName,
+ tempObjectArg,
+ nestedAction.arg(idx)))
+ {
+ if(tempObjectName == "Name")
+ {
+ layerName = tempObjectArg;
+ }
+ else if(tempObjectName == "Id")
+ {
+ id = tempObjectArg;
+ }
+ }
+ }
+ osg::ref_ptr<ossimPlanetTextureLayer> layer;
+ if(!id.empty()&&!layerName.empty())
+ {
+ layer = referenceLayer()->findLayerByNameAndId(layerName, id);
+ }
+ else if(!id.empty())
+ {
+ layer = referenceLayer()->findLayerById(id, true);
+ }
+ else if(!layerName.empty())
+ {
+ layer = referenceLayer()->findLayerByName(layerName, true);
+ }
+ if(layer.valid())
+ {
+ layer->remove();
+ }
+ }
+ }
+ }
+#endif
+}
+
+void ossimPlanetLand::resetGraph(const ossimPlanetAction& /*a*/)
+{
+#if 0
+ if(a.argCount() == 0)
+ {
+ resetGraph();
+ }
+ else
+ {
+ ossimString bbox = "-180,-90,180,90";
+ ossimString scaleRangeString = "";
+ double minLat = -90.0, minLon = -180.0, maxLat = 90.0, maxLon = 180.0;
+ ossimString refreshTypeString = "all";
+ ossimString objectName;
+ ossimString objectArg;
+ ossim_uint32 idx = 1;
+ for(idx = 1; idx <= (ossim_uint32)a.argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ a.arg(idx)))
+ {
+ if(objectName == "Extents")
+ {
+ ossimPlanetAction nestedAction(": Extents " + objectArg);
+ ossim_uint32 idx2=1;
+ for(;idx2 <= (ossim_uint32)nestedAction.argCount(); ++idx2)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ nestedAction.arg(idx2)))
+ {
+ if(objectName == "Bbox")
+ {
+ bbox = objectArg;
+ }
+ else if(objectName == "ScaleRange")
+ {
+ scaleRangeString = objectArg;
+ }
+ }
+ }
+ }
+ else if(objectName == "Type")
+ {
+ refreshTypeString = objectArg;
+ }
+ }
+ }
+ osg::ref_ptr<ossimPlanetExtents> extents = new ossimPlanetExtents;
+ ossimPlanetLandRefreshType refreshType = ossimPlanetLandRefreshType_PRUNE;
+ std::vector<ossimString> splitVector;
+ bbox.split(splitVector, ",");
+ if(splitVector.size() == 4)
+ {
+ minLon = splitVector[0].toDouble();
+ minLat = splitVector[1].toDouble();
+ maxLon = splitVector[2].toDouble();
+ maxLat = splitVector[3].toDouble();
+ }
+ refreshTypeString = refreshTypeString.downcase();
+ if(refreshTypeString == "texture")
+ {
+ refreshType = ossimPlanetLandRefreshType_TEXTURE;
+ }
+ else if(refreshTypeString == "geometry")
+ {
+ refreshType = ossimPlanetLandRefreshType_GEOM;
+ }
+ extents->setMinMaxLatLon(minLat, minLon, maxLat, maxLon);
+ if(!scaleRangeString.empty())
+ {
+ splitVector.clear();
+ scaleRangeString.split(splitVector,",");
+ if(splitVector.size() == 2)
+ {
+ extents->setMinMaxScale(splitVector[0].toDouble(),
+ splitVector[1].toDouble());
+ }
+ }
+ resetGraph(extents,refreshType);
+ }
+#endif
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLandCache.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLandCache.cpp
new file mode 100644
index 0000000..7fda66b
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLandCache.cpp
@@ -0,0 +1,290 @@
+#include <ossimPlanet/ossimPlanetLandCache.h>
+
+
+void ossimPlanetLandCacheNode::access()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theTimeStamp = osg::Timer::instance()->tick();
+}
+
+void ossimPlanetLandCacheNode::protectedAccess()
+{
+ theTimeStamp = osg::Timer::instance()->tick();
+
+}
+
+void ossimPlanetLandCacheNode::setExtents(osg::ref_ptr<ossimPlanetExtents> extents)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theExtents = extents.get();
+}
+
+void ossimPlanetLandCacheNode::setTexture(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetImage> texture)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ if(idx >= theTextureList.size())
+ {
+
+ if(idx == theTextureList.size())
+ {
+ theTextureList.push_back(texture.get());
+ }
+ else
+ {
+ std::vector<osg::ref_ptr<ossimPlanetImage> > tempVec = theTextureList;
+
+ theTextureList.resize(idx-(theTextureList.size()-1));
+ theTextureList.insert(theTextureList.begin(),
+ tempVec.begin(),
+ tempVec.end());
+ theTextureList[idx] = texture.get();
+ }
+ }
+ else
+ {
+ theTextureList[idx] = texture.get();
+ }
+
+ adjustSize();
+ protectedAccess();
+}
+
+void ossimPlanetLandCacheNode::clearTextures()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ theTextureList.clear();
+ adjustSize();
+ protectedAccess();
+}
+
+void ossimPlanetLandCacheNode::setElevation(osg::ref_ptr<ossimPlanetImage> elevation)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theElevation = elevation.get();
+ adjustSize();
+}
+
+void ossimPlanetLandCacheNode::setLandCache(ossimPlanetLandCache* landCache)
+{
+ theLandCache = landCache;
+}
+
+ossim_uint64 ossimPlanetLandCacheNode::getNodeSizeInBytes()const
+{
+ return theNodeSizeInBytes;
+}
+
+void ossimPlanetLandCacheNode::estimateSize()
+{
+ theNodeSizeInBytes = (sizeof(osg::Timer_t)+sizeof(OpenThreads::Mutex)+sizeof(theId)+sizeof(theNodeSizeInBytes)+
+ sizeof(theExtents)+sizeof(theTextureList)+sizeof(theElevation)+sizeof(theLandCache));
+
+ if(theElevation.valid())
+ {
+ theNodeSizeInBytes += theElevation->getTotalSizeInBytes();
+ }
+
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theTextureList.size();++idx)
+ {
+ if(theTextureList[idx].valid())
+ {
+ theNodeSizeInBytes += theTextureList[idx]->getTotalSizeInBytes();
+ }
+ }
+}
+
+void ossimPlanetLandCacheNode::adjustSize()
+{
+ if(theLandCache)
+ {
+ theLandCache->theCurrentCacheSize -= theNodeSizeInBytes;
+ estimateSize();
+ theLandCache->theCurrentCacheSize += theNodeSizeInBytes;
+ theLandCache->shrinkCache();
+ }
+ else
+ {
+ estimateSize();
+ }
+}
+
+ossimPlanetLandCache::ossimPlanetLandCache(ossim_uint64 maxCacheSize, ossim_uint64 minCacheSize)
+{
+ theMinCacheSize = minCacheSize;
+ theMaxCacheSize = maxCacheSize;
+}
+
+bool ossimPlanetLandCache::addNode(ossimPlanetLandCacheNode* node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(!node) return false;
+ if(theMaxCacheSize < node->getNodeSizeInBytes()) return false;
+
+ ossimPlanetLandCacheType::iterator iter = theCacheMap.find(node->getId());
+
+ if(iter != theCacheMap.end())
+ {
+ iter->second = node;
+ iter->second->access();
+ }
+ else
+ {
+ node->setLandCache(this);
+ theCacheMap.insert(std::make_pair(node->getId(),
+ node));
+ theCurrentCacheSize += node->getNodeSizeInBytes();
+ }
+
+ shrinkCache();
+
+ return true;
+}
+
+ossimPlanetLandCacheNode* ossimPlanetLandCache::getNode(ossim_uint64 id, bool allocateNewNodeIfNotPresent)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(theMaxCacheSize == 0) return 0;
+ ossimPlanetLandCacheType::iterator iter = theCacheMap.find(id);
+ if(iter != theCacheMap.end())
+ {
+ iter->second->access();
+
+ return iter->second.get();
+ }
+ if(allocateNewNodeIfNotPresent)
+ {
+ ossimPlanetLandCacheNode* newNode = new ossimPlanetLandCacheNode(this, id);
+
+ addNode(newNode);
+
+ return newNode;
+ }
+ return 0;
+}
+
+osg::ref_ptr<ossimPlanetLandCacheNode> ossimPlanetLandCache::removeNode(ossim_uint64 id)
+{
+ osg::ref_ptr<ossimPlanetLandCacheNode> result;
+ ossimPlanetLandCacheType::iterator iter = theCacheMap.find(id);
+
+ if(iter != theCacheMap.end())
+ {
+ result = iter->second;
+ }
+
+ return result.get();
+}
+
+void ossimPlanetLandCache::setCacheSize(ossim_uint64 maxCacheSize, ossim_uint64 minCacheSize)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theMaxCacheSize = ossim::max(maxCacheSize, minCacheSize);
+ theMinCacheSize = ossim::min(maxCacheSize, minCacheSize);
+ protectedShrinkCache();
+}
+
+ossim_uint64 ossimPlanetLandCache::getCacheSize()const
+{
+ return theMaxCacheSize;
+}
+
+void ossimPlanetLandCache::shrinkCache()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ protectedShrinkCache();
+}
+void ossimPlanetLandCache::clearCache()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theCacheMap.clear();
+ theCurrentCacheSize = 0;
+}
+
+void ossimPlanetLandCache::clearAllWithinExtents(osg::ref_ptr<ossimPlanetExtents> extents)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimPlanetLandCacheType::iterator iter = theCacheMap.begin();
+
+ while(iter != theCacheMap.end())
+ {
+ if(iter->second->getExtents())
+ {
+ if(iter->second->getExtents()->intersects(*extents))
+ {
+ ossimPlanetLandCacheType::iterator currentIter = iter;
+ ++iter;
+ theCurrentCacheSize -= currentIter->second->getNodeSizeInBytes();
+ theCacheMap.erase(currentIter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+}
+
+void ossimPlanetLandCache::clearTexturesWithinExtents(osg::ref_ptr<ossimPlanetExtents> extents)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimPlanetLandCacheType::iterator iter = theCacheMap.begin();
+
+ while(iter != theCacheMap.end())
+ {
+ if(iter->second->getExtents())
+ {
+ if(iter->second->getExtents()->intersects(*extents))
+ {
+ theMutex.unlock();
+ iter->second->clearTextures();
+ theMutex.lock();
+ }
+ }
+ ++iter;
+ }
+}
+
+
+void ossimPlanetLandCache::protectedShrinkCache()
+{
+ if((theCurrentCacheSize > theMaxCacheSize)&&theCacheMap.size() > 0)
+ {
+ osg::Timer_t timeStamp;
+ while((theCurrentCacheSize > theMinCacheSize)&&(theCacheMap.size() > 0))
+ {
+ ossimPlanetLandCacheType::iterator iter = theCacheMap.begin();
+ ossimPlanetLandCacheType::iterator smallestTimeStampIter = iter;
+ timeStamp = iter->second->timeStamp();
+
+ ++iter;
+ while(iter != theCacheMap.end())
+ {
+ if(iter->second->timeStamp() < timeStamp)
+ {
+ smallestTimeStampIter = iter;
+ timeStamp = iter->second->timeStamp();
+ }
+
+ ++iter;
+ }
+
+ if(smallestTimeStampIter!=theCacheMap.end())
+ {
+ theCurrentCacheSize -= smallestTimeStampIter->second->getNodeSizeInBytes();
+ theCacheMap.erase(smallestTimeStampIter);
+ }
+ }
+ }
+ if(theCacheMap.size() == 0)
+ {
+ theCurrentCacheSize = 0;
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLandCullCallback.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLandCullCallback.cpp
new file mode 100644
index 0000000..75a91f7
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLandCullCallback.cpp
@@ -0,0 +1,481 @@
+#include <ossimPlanet/ossimPlanetLandCullCallback.h>
+#include <ossimPlanet/ossimPlanetPagedLandLod.h>
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <osgUtil/CullVisitor>
+#include <osgUtil/IntersectVisitor>
+#include <ossim/base/ossimDrect.h>
+#include <osg/LineSegment>
+
+ossimPlanetLandCullCallback::ossimPlanetLandCullCallback()
+ :osg::NodeCallback(),
+ theFreezeRequestFlag(false),
+ theCullingFlag(true),
+ theSplitMetric(3.0),
+ theSplitPriorityType(ossimPlanetLandPriorityType_LINE_OF_SITE_INTERSECTION),
+ theLineOfSiteValidFlag(false)
+{
+}
+
+void ossimPlanetLandCullCallback::setLineOfSite(const osg::Vec3d& lineOfSite)
+{
+ theLineOfSite = lineOfSite;
+ theLineOfSiteValidFlag = false;
+ if((!ossim::isnan(theLineOfSite[0]))&&
+ (!ossim::isnan(theLineOfSite[1]))&&
+ (!ossim::isnan(theLineOfSite[2])))
+ {
+ theLineOfSiteValidFlag = true;
+ }
+}
+
+void ossimPlanetLandCullCallback::setLineOfSiteValidFlag(bool flag)
+{
+ theLineOfSiteValidFlag = flag;
+}
+
+bool ossimPlanetLandCullCallback::isLineOfSiteValid()const
+{
+ return theLineOfSiteValidFlag;
+}
+
+void ossimPlanetLandCullCallback::setSplitMetricRatio(double ratio)
+{
+ theSplitMetric = ratio;
+}
+
+double ossimPlanetLandCullCallback::getSplitMetricRatio()const
+{
+ return theSplitMetric;
+}
+
+void ossimPlanetLandCullCallback::setSplitPriorityType(ossimPlanetPriorityType priorityType)
+{
+ theSplitPriorityType = priorityType;
+}
+
+ossimPlanetPriorityType ossimPlanetLandCullCallback::getSplitPriorityType()const
+{
+ return theSplitPriorityType;
+}
+
+void ossimPlanetLandCullCallback::setCullingFlag(bool flag)
+{
+ theCullingFlag = flag;
+}
+
+bool ossimPlanetLandCullCallback::getCullingFlag()const
+{
+ return theCullingFlag;
+}
+
+void ossimPlanetLandCullCallback::setFreezeRequestFlag(bool flag)
+{
+ theFreezeRequestFlag = flag;
+}
+
+bool ossimPlanetLandCullCallback::getFreezRequestFlag()const
+{
+ return theFreezeRequestFlag;
+}
+
+void ossimPlanetLandCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+ ossimPlanetPagedLandLod* n = dynamic_cast<ossimPlanetPagedLandLod*>(node);
+ if(n)
+ {
+ applyStandardCull(n, nv);
+ }
+}
+
+void ossimPlanetLandCullCallback::applyStandardCull(ossimPlanetPagedLandLod* n, osg::NodeVisitor* nv)
+{
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
+ if(n->theRefreshType == ossimPlanetLandRefreshType_PRUNE)
+ {
+ if(n->getNumChildren() > 0)
+ {
+ if(n->getChild(0))
+ {
+ n->getChild(0)->accept(*nv);
+ }
+ }
+
+ return;
+ }
+ if(!cullVisitor)
+ {
+ if(n->isLeaf())
+ {
+ n->getChild(0)->accept(*nv);
+ }
+ else
+ {
+ traverse(n, nv);
+ }
+ return;
+ }
+ const osg::BoundingSphere& bs = n->getBound();
+ bool canCull = true;
+// bool canCull = n->theLevel >0;//theCullingFlag;
+ n->theRemoveChildrenFlag = false;
+ bool addChildrenFlag = false;
+ double ratio = theSplitMetric;
+
+ // let's always keep level 0.
+ //
+// if(n->theLevel < 1) ratio = 99999.0;
+
+ n->theRemoveChildrenFlag = false;
+ osg::Vec3 real_eye = cullVisitor->getEyeLocal();
+
+ double fov_y, aspect_ratio, z_near, z_far;
+ cullVisitor->getProjectionMatrix()->getPerspective(fov_y, aspect_ratio, z_near, z_far );
+
+ osg::Vec3d apparent_eye = real_eye;
+ // osg::Vec3d down_eye = real_eye;
+
+ if( theLineOfSiteValidFlag )
+ {
+ osg::Vec3d look_vector = theLineOfSite - real_eye;
+
+ double opposite = look_vector.length() * tan( osg::DegreesToRadians(fov_y/2.0) );
+ double camera_dist = opposite / tan( osg::DegreesToRadians(50.0/2.0) );
+
+ apparent_eye = theLineOfSite - (look_vector * (camera_dist / look_vector.length()));
+ }
+
+ double radius = bs.radius();
+// double radius = (n->theCullNode->boundingBox()->radius());
+// double distance = n->theCullNode->eyeDistance();
+ double real_distance = (real_eye-bs.center()).length();
+ double apparent_distance = (apparent_eye-bs.center()).length();
+ double distance = min( apparent_distance, real_distance ); // this will keep around tiles close to the eye
+
+// double pixelSize = cullVisitor->clampedPixelSize(bs);
+ n->theCulledFlag = false;
+ if(canCull)
+ {
+ n->theCullNode->accept(*nv);
+ n->theCulledFlag = n->theCullNode->isCulled();
+ }
+
+ if((distance < radius*ratio))
+// if(pixelSize >= 512)
+ {
+ if(n->getNumChildren() < 5)
+ {
+ addChildrenFlag = true;
+ }
+ }
+ else if( distance > 2*radius*ratio )
+// else if(pixelSize < 256)
+ {
+ n->theRemoveChildrenFlag = true;
+ }
+ if(addChildrenFlag && ((n->theLevel+1)>n->theMaxLevel))
+ {
+ addChildrenFlag = false;
+ }
+ double priority = 0.0;
+ osg::Vec3d priorityPoint = apparent_eye;
+
+
+ if((theSplitPriorityType==ossimPlanetLandPriorityType_LINE_OF_SITE_INTERSECTION)&&theLineOfSiteValidFlag)
+ {
+ priorityPoint = theLineOfSite;
+ }
+
+ priority = (priorityPoint-bs.center()).length();
+ priority *= 1<<n->theLevel;
+ if(priority > 0.0)
+ {
+ priority = 1.0/priority;
+ }
+ else
+ {
+ priority = 1.0/FLT_EPSILON;
+ }
+ ossimString postFixRefreshType = "";
+ if( (n->theRefreshType&ossimPlanetLandRefreshType_GEOM)&&
+ (n->theRefreshType&ossimPlanetLandRefreshType_TEXTURE))
+ {
+ postFixRefreshType = "_GEOM_TEXTURE";
+ }
+ else if(n->theRefreshType&ossimPlanetLandRefreshType_GEOM)
+ {
+ postFixRefreshType = "_GEOM";
+ }
+ else if(n->theRefreshType&ossimPlanetLandRefreshType_TEXTURE)
+ {
+ postFixRefreshType = "_TEXTURE";
+
+ }
+ if(!postFixRefreshType.empty()&&!theFreezeRequestFlag)
+ {
+ if(n->isLeaf())
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+postFixRefreshType,
+ cullVisitor->getNodePath(),
+ 9999999*priority*((std::pow(2.0, (double)n->theLevel))),
+ nv->getFrameStamp(),
+ n->theRequestRef,
+ 0);
+ }
+ else
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+postFixRefreshType,
+ cullVisitor->getNodePath(),
+ priority*((std::pow(2.0, (double)n->theLevel))),
+ nv->getFrameStamp(),
+ n->theRequestRef,
+ 0);
+ }
+ addChildrenFlag = false;
+
+ }
+
+ if(addChildrenFlag&&!n->theCulledFlag&&!n->theRemoveChildrenFlag)
+ {
+ ossim_uint32 idx = 0;
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockChildList(n->theChildCullNodeListMutex);
+ ossim_uint32 cullCount = 0;
+ for(idx = 0; ((idx < n->theChildCullNodeList.size())&&n->theChildCullNodeList[idx].valid()); ++idx)
+ {
+ n->theChildCullNodeList[idx]->accept(*cullVisitor);
+
+ if(n->theChildCullNodeList[idx]->isCulled())
+ {
+ ++cullCount;
+ }
+ }
+ if(idx >= n->theChildCullNodeList.size())
+ {
+ addChildrenFlag = cullCount != n->theChildCullNodeList.size();
+ }
+ }
+ int childIdx = n->thePagedLodList.size();
+ std::string requestString = ((n->getNumChildren() < 5)&&(n->thePagedLodList.size()<4))?n->theRequestNameList[childIdx+1]:"";
+ if(!theFreezeRequestFlag&&
+ (requestString!= "")&&
+ cullVisitor->getDatabaseRequestHandler())
+ {
+ if(!n->theRemoveChildrenFlag &&
+ addChildrenFlag&&
+ !n->theCulledFlag&&
+ (n->getNumChildren() < 5))
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(requestString,
+ cullVisitor->getNodePath(),
+ priority,
+ nv->getFrameStamp(),
+ n->theRequestRefChildList[childIdx]);
+ }
+ }
+ if(!n->isLeaf())
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 1; idx < n->getNumChildren(); ++idx)
+ {
+ if(n->getChild(idx))
+ {
+ n->getChild(idx)->accept(*nv);
+ }
+ }
+// if(n->areAllChildrenCulled(true)&&!n->theCulledFlag)
+// {
+// if(n->getChild(0))
+// {
+// n->getChild(0)->accept(*nv);
+// }
+// }
+ }
+ else
+ {
+ if(n->getNumChildren() > 0)
+ {
+ if(n->getChild(0))
+ {
+ if(!n->theCulledFlag)
+ {
+ n->getChild(0)->accept(*nv);
+ }
+ }
+ }
+ }
+}
+
+#if 0
+void ossimPlanetLandCullCallback::applyOrthoCull(ossimPlanetPagedLandLod* n,
+ osg::NodeVisitor* nv)
+{
+ //OpenThreads::ScopedLock<OpenThreads::Mutex> lock(n->theMutex);
+
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
+ if(n->theRefreshType == ossimPlanetLandRefreshType_PRUNE)
+ {
+ if(n->getNumChildren() > 0)
+ {
+ if(n->getChild(0))
+ {
+ n->getChild(0)->accept(*nv);
+ }
+ }
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+"_GEOM",
+ n,
+ 99999999,
+ nv->getFrameStamp());
+ return;
+ }
+ if(!cullVisitor) return;
+ n->theCulledFlag = false;
+ bool addChildrenFlag = false;
+ n->theRemoveChildrenFlag = false;
+ double distance=0.0;
+ osg::Matrix wm = cullVisitor->getWindowMatrix();
+
+ const osg::RefMatrix& m = *(cullVisitor->getMVPW());
+ double x = cullVisitor->getViewport()->x();
+ double y = cullVisitor->getViewport()->y();
+ double w = cullVisitor->getViewport()->width();
+ double h = cullVisitor->getViewport()->height();
+ if(w < 1) w = 1;
+ if(h < 1) h = 1;
+ ossimDrect viewportRect(x,
+ y,
+ x + (w-1),
+ y + (h-1));
+ wm = osg::Matrixd::inverse(*cullVisitor->getProjectionMatrix());
+
+ osg::Vec3d center = (osg::Vec3d(0.0,0.0, 1.0)*wm);
+ osg::Vec3d projectedCenter = (n->theCenterPoint*m);
+ distance = (center-n->getBound().center()).length();
+// distance = (center-n->getBound().center()).length()/(sqrt(180.0*180.0 + 90.0*90.0));
+//
+// distance = (osg::Vec2d(projectedCenter[0],
+// projectedCenter[1]) -
+// osg::Vec2d(w/2.0,
+// h/2.0)).length();
+
+ osg::Vec3d ulView = n->theUlPoint*m;
+ osg::Vec3d urView = n->theUrPoint*m;
+ osg::Vec3d lrView = n->theLrPoint*m;
+ osg::Vec3d llView = n->theLlPoint*m;
+ ossimDpt ulViewDpt(ulView[0], ulView[1]);
+ ossimDpt urViewDpt(urView[0], urView[1]);
+ ossimDpt lrViewDpt(lrView[0], lrView[1]);
+ ossimDpt llViewDpt(llView[0], llView[1]);
+ ossimDrect rect(ulViewDpt,
+ urViewDpt,
+ lrViewDpt,
+ llViewDpt);
+
+ n->theCulledFlag = !rect.intersects(viewportRect);
+
+ float pixelSize = ossim::max(rect.width(), rect.height());
+ if(pixelSize >= 512)
+ {
+ if(n->isLeaf())
+ {
+ addChildrenFlag = true;
+ }
+ }
+ else if(pixelSize < 256)
+ {
+// if(!n->isLeaf())
+ {
+ n->theRemoveChildrenFlag = true;
+ }
+ }
+
+ distance *= 1<<n->theLevel;
+ double priority = 0.0;
+ if(distance > 0.0)
+ {
+ priority = 1.0/distance;
+ }
+ else
+ {
+ priority = 1.0/FLT_EPSILON;
+ }
+ if((n->theRefreshType == ossimPlanetLandRefreshType_GEOM)&&(!n->theCulledFlag))
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+"_GEOM",
+ n,
+ priority,
+ nv->getFrameStamp());
+ }
+ else if((n->theRefreshType == ossimPlanetLandRefreshType_TEXTURE)&&(!n->theCulledFlag))
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+"_TEXTURE",
+ n,
+ priority,
+ nv->getFrameStamp());
+ }
+ std::string requestString = ((n->getNumChildren() < 5)&&(n->thePagedLodList.size()<4))?n->theRequestNameList[n->thePagedLodList.size()+1]:"";
+// std::string requestString = (n->getNumChildren() < 5)?n->getRequestName(n->getNumChildren()):"";
+ if((requestString!= "")&&
+ cullVisitor->getDatabaseRequestHandler())
+ {
+ if((n->theRefreshType == ossimPlanetLandRefreshType_GEOM)&&(!n->theCulledFlag))
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+"_GEOM",
+ n,
+ priority,
+ nv->getFrameStamp());
+ }
+ else if((n->theRefreshType == ossimPlanetLandRefreshType_TEXTURE)&&(!n->theCulledFlag))
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(n->theRequestNameList[0]+"_TEXTURE",
+ n,
+ priority,
+ nv->getFrameStamp());
+ }
+ if(!n->theRemoveChildrenFlag &&
+ addChildrenFlag&&
+ !n->theCulledFlag&&
+ (n->getNumChildren() < 5))
+ {
+ cullVisitor->getDatabaseRequestHandler()->requestNodeFile(requestString,
+ n,
+ priority,
+ nv->getFrameStamp());
+ }
+ else if((n->theCulledFlag)&&
+ (n->isLeaf())&&
+ (n->getNumChildren()>1))
+ {
+ ossimPlanetDatabasePager* pager = dynamic_cast<ossimPlanetDatabasePager*>(cullVisitor->getDatabaseRequestHandler());
+ if(pager)
+ {
+ pager->invalidateRequest(requestString);
+ }
+ }
+ }
+ if(!n->theCulledFlag)
+ {
+ if(n->getNumChildren() >4)
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 1; idx < n->getNumChildren(); ++idx)
+ {
+ if(n->getChild(idx))
+ {
+ n->getChild(idx)->accept(*nv);
+ }
+ }
+ }
+ else
+ {
+ if(n->getNumChildren() > 0)
+ {
+ if(n->getChild(0))
+ {
+ n->getChild(0)->accept(*nv);
+ }
+ }
+ }
+ }
+}
+#endif
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLandReaderWriter.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLandReaderWriter.cpp
new file mode 100644
index 0000000..476edaa
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLandReaderWriter.cpp
@@ -0,0 +1,1864 @@
+#include <ossimPlanet/ossimPlanetLandReaderWriter.h>
+#include <ossimPlanet/ossimPlanetPlaneGrid.h>
+#include <ossimPlanet/ossimPlanetCubeGrid.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include <osg/CullFace>
+#include <osg/Program>
+#include <osg/Uniform>
+#include <osgUtil/SmoothingVisitor>
+#include <osgUtil/GLObjectsVisitor>
+#include <osgUtil/Optimizer>
+#include <osgUtil/CullVisitor>
+#include <osg/PagedLOD>
+#include <osgUtil/SmoothingVisitor>
+#include <osgUtil/TriStripVisitor>
+#include <osgDB/Registry>
+#include <OpenThreads/ScopedLock>
+#include <ossimPlanet/ossimPlanetBoundingBox.h>
+#include <ossimPlanet/ossimPlanetLandTextureRequest.h>
+#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <ossim/elevation/ossimElevManager.h>
+// #include <ossimPlanet/ossimPlanetElevationGrid.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetPagedLandLod.h>
+#include <ossimPlanet/ossimPlanetTexture2D.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <osgUtil/Simplifier>
+#include <ossim/base/ossimGeoidManager.h>
+
+static ossim_uint32 landReaderWriterId = 0;
+
+ossimPlanetLandReaderWriter::ossimPlanetLandReaderWriter()
+ :theId(landReaderWriterId++)
+{
+ theLandType = ossimPlanetLandType_NORMALIZED_ELLIPSOID;
+ theMaxLevelDetail = 18;
+ theHeightExag = 1.0;
+ theElevationPatchSize= 17;
+ theElevationEnabledFlag = true;
+ theMultiTextureEnableFlag = false;
+ theMipMappingFlag = true;
+ theGrid = new ossimPlanetCubeGrid;
+ theElevationGrid = new ossimPlanetCubeGrid;
+}
+
+const char* ossimPlanetLandReaderWriter::className()const
+{
+ return "ossimPlanetLandReaderWriter";
+}
+
+osgDB::ReaderWriter::ReadResult ossimPlanetLandReaderWriter::readNode(const std::string& filename, const Options* /* options */ )const
+{
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(!theModel.valid()) return 0;
+ // std::cout << "ossimPlanetLandReaderWriter::readNode filename = " << filename << std::endl;
+ osgDB::ReaderWriter::ReadResult result = 0;
+ if(filename == "") return result;
+ ossim_uint32 level;
+ ossim_uint32 row;
+ ossim_uint32 col;
+ ossim_uint32 id;
+ ossimPlanetLandReaderWriterGeomType geomType = ossimPlanetLandReaderWriterGeomType_NONE;
+
+ if(!extractValues(filename,
+ level,
+ row,
+ col,
+ id,
+ geomType))
+ {
+ return result;
+ }
+// std::cout << "level = " << level << std::endl;
+ if(id != theId)
+ {
+ return result;
+ }
+ osg::Vec3d centerPoint;
+ osg::Vec3d ulPoint;
+ osg::Vec3d urPoint;
+ osg::Vec3d lrPoint;
+ osg::Vec3d llPoint;
+ osg::Vec3d centerNormal;
+ osg::Vec3d ulNormal;
+ osg::Vec3d urNormal;
+ osg::Vec3d lrNormal;
+ osg::Vec3d llNormal;
+ osg::ref_ptr<ossimPlanetBoundingBox> box = new ossimPlanetBoundingBox;
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+// unsigned int w = theUtility.getTileWidth();
+// unsigned int h = theUtility.getTileHeight();
+ theGrid->getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row, // row
+ col);
+ ossim_uint64 tileId = theGrid->getId(level, row, col);
+ osg::ref_ptr<ossimPlanetLandCacheNode> cacheNode = theLandCache->getNode(tileId, true);
+ if(cacheNode.valid())
+ {
+ double dx, dy;
+ theGrid->getPixelScaleAsMeters(dx, dy, level, row, col);
+ double scale = (dx+dy)*.5;
+ ossimPlanetExtents* extents = new ossimPlanetExtents;
+ extents->setMinMaxLatLon(minLat, minLon, maxLat, maxLon);
+ extents->setMinMaxScale(scale*.5, scale*2.0);
+
+ cacheNode->setExtents(extents);
+ }
+
+ ossimPlanetImage::ossimPlanetImageStateType textureState = ossimPlanetImage::ossimPlanetImageStateType_LOADED;
+ osg::ref_ptr<ossimPlanetImage> elevationGrid;
+
+ std::vector<osg::ref_ptr<osg::Texture2D> > textures;
+ newTexture(textures,
+ level,
+ row,
+ col,
+ textureState);
+
+ if(geomType & ossimPlanetLandReaderWriterGeomType_TEXTURE)
+ {
+ ossimPlanetLandTextureRequest* landRequest = new ossimPlanetLandTextureRequest(level, row, col, textures);
+ osgUtil::GLObjectsVisitor v;
+ landRequest->setTextureState(textureState);
+
+ landRequest->accept(v);
+
+ return landRequest;
+ }
+ if(geomType & (ossimPlanetLandReaderWriterGeomType_GEOM|ossimPlanetLandReaderWriterGeomType_LOD))
+ {
+ elevationGrid = newElevation(level, row, col);
+ }
+ osg::ref_ptr<ossimPlanetPagedLandLod> pagedLod;
+ if(geomType & ossimPlanetLandReaderWriterGeomType_LOD)
+ {
+ pagedLod = new ossimPlanetPagedLandLod(level, row, col, filename);
+ }
+ osg::ref_ptr<ossimPlanetBoundingBox> boundingBox = new ossimPlanetBoundingBox;
+ bool useClusterCulling = false;
+ osg::Vec3d clusterControlPoint ;
+ osg::Vec3d clusterCenterNormal;
+ double minDotProduct;
+ double maxClusterCullingRadius;
+ osg::ref_ptr<osg::MatrixTransform> trans = newGeometry(level,
+ row,
+ col,
+ textures,
+ elevationGrid,
+ *boundingBox,
+ useClusterCulling,
+ clusterControlPoint,
+ clusterCenterNormal,
+ minDotProduct,
+ maxClusterCullingRadius);
+ std::vector<ossimPlanetBoundingBox> childrenBounds;
+
+ if(!pagedLod.valid())
+ {
+ ossimPlanetLandTextureRequest* landRequest = new ossimPlanetLandTextureRequest(level, row, col, textures);
+ landRequest->setTextureState(textureState);
+// landRequest->setTransform(trans);
+ landRequest->setCullCallback(theCullNodeCallback.get());
+ initSupportAttributes(level,
+ row,
+ col,
+ centerPoint,
+ ulPoint,
+ urPoint,
+ lrPoint,
+ llPoint,
+ centerNormal,
+ ulNormal,
+ urNormal,
+ lrNormal,
+ llNormal,
+ *box,
+ childrenBounds,
+ *trans);
+ landRequest->setCenterPoint(centerPoint);
+ landRequest->setUlPoint(ulPoint);
+ landRequest->setUrPoint(urPoint);
+ landRequest->setLrPoint(lrPoint);
+ landRequest->setLlPoint(llPoint);
+ landRequest->setCenterNormal(centerNormal);
+ landRequest->setUlNormal(ulNormal);
+ landRequest->setUrNormal(urNormal);
+ landRequest->setLrNormal(lrNormal);
+ landRequest->setLlNormal(llNormal);
+// if(level == 0)
+// {
+// landRequest->setBoundingBox(box);
+// }
+// else
+// {
+ landRequest->setBoundingBox(boundingBox);
+// }
+// landRequest->setChildrenBounds(childrenBounds);
+// osgUtil::GLObjectsVisitor v;
+
+// landRequest->accept(v);
+
+// if(useClusterCulling)
+// {
+// landRequest->setClusterCullValues(useClusterCulling,
+// clusterControlPoint,
+// clusterCenterNormal,
+// minDotProduct,
+// maxClusterCullingRadius);
+// }
+ return landRequest;
+ }
+
+ if(theGrid->getNumberOfFaces() <3)
+ {
+ ossimPlanetGridUtility::GridPoint centerGridPoint;
+
+ theGrid->getCenterGridPoint(centerGridPoint, level, row, col);
+
+ theGrid->getLatLon(centerPoint, centerGridPoint);
+ if(centerPoint[0] > 60.0)
+ {
+ pagedLod->theMaxLevel = ((minLat > 80.0)?4:99999999);
+ }
+ else if(centerPoint[0] < -60)
+ {
+ pagedLod->theMaxLevel = ((maxLat < -80.0)?4:99999999);
+ }
+ else
+ {
+ pagedLod->theMaxLevel = 99999999;
+ }
+ }
+// pagedLod->theTransform = trans.get();
+
+ osg::ref_ptr<osg::Geode> geode = dynamic_cast<osg::Geode*>(trans->getChild(0));
+ if(geode.valid())
+ {
+// geode->getDrawable(0)->setDrawCallback(new ossimPlanetPagedLandDrawableCallback(pagedLod.get()));
+// geode->getDrawable(0)->setDrawCallback(new ossimPlanetPagedLandDrawableCallback(level, row, col));
+ }
+
+ initSupportAttributes(level,
+ row,
+ col,
+ centerPoint,
+ ulPoint,
+ urPoint,
+ lrPoint,
+ llPoint,
+ centerNormal,
+ ulNormal,
+ urNormal,
+ lrNormal,
+ llNormal,
+ *box,
+ childrenBounds,
+ *trans);
+ pagedLod->theGeode = geode;
+ pagedLod->theCenterPoint = centerPoint;
+ pagedLod->theUlPoint = ulPoint;
+ pagedLod->theUrPoint = urPoint;
+ pagedLod->theLrPoint = lrPoint;
+ pagedLod->theLlPoint = llPoint;
+ pagedLod->theCenterNormal = centerNormal;
+ pagedLod->theUlNormal = ulNormal;
+ pagedLod->theUrNormal = urNormal;
+ pagedLod->theLrNormal = lrNormal;
+ pagedLod->theLlNormal = llNormal;
+
+ pagedLod->theCullNode = new ossimPlanetPagedLandLodCullNode(boundingBox,
+ useClusterCulling,
+ clusterControlPoint,
+ clusterCenterNormal,
+ minDotProduct,
+ maxClusterCullingRadius);
+ pagedLod->theCullNode->setMatrix(trans->getMatrix());
+
+ int face = theGrid->getFace(level, row, col);
+ ossim_uint64 wide;
+ ossim_uint64 high;
+ ossim_uint64 originX = col;
+// ossim_uint64 originY = row;
+
+ theGrid->getNumberOfTilesWideHighPerFace(wide, high, level);
+
+ originX -= face*wide;
+ theGrid->getNumberOfTilesWideHighPerFace(wide, high, level+1);
+
+ pagedLod->setCullCallback(theCullNodeCallback.get());
+ pagedLod->addChild(trans.get());
+
+
+ pagedLod->setRequestName(0,
+ createDbString(level,
+ row,
+ col));
+ if(textureState == ossimPlanetImage::ossimPlanetImageStateType_NEEDS_LOADING)
+ {
+ pagedLod->setRefreshType(ossimPlanetLandRefreshType_TEXTURE);
+ }
+ if(level+1 <= theMaxLevelDetail)
+ {
+ pagedLod->setRequestName(1,
+ createDbString(level+1,
+ row<<1,
+ (originX<<1)+(face*wide)));
+ pagedLod->setRequestName(2,
+ createDbString(level+1,
+ row<<1,
+ ((originX<<1) + 1)+(face*wide)));
+ pagedLod->setRequestName(3,
+ createDbString(level+1,
+ (row<<1)+1,
+ ((originX<<1)+1)+(face*wide)));
+ pagedLod->setRequestName(4,
+ createDbString(level+1,
+ (row<<1)+1,
+ (originX<<1)+(face*wide)));
+ }
+ else
+ {
+ pagedLod->setRequestName(1,
+ "");
+ pagedLod->setRequestName(2,
+ "");
+ pagedLod->setRequestName(3,
+ "");
+ pagedLod->setRequestName(4,
+ "");
+ }
+
+// osgUtil::GLObjectsVisitor v;
+
+// pagedLod->accept(v);
+// osgUtil::Optimizer opt;
+// opt.optimize(pagedLod.get());
+
+// osgUtil::SmoothingVisitor smooth;
+
+// pagedLod->accept(smooth);
+ return pagedLod.get();
+}
+
+
+// osgDB::ReaderWriter::ReadResult ossimPlanetLandReaderWriter::local_readNode(const std::string& filename,
+// const Options* options)const
+// {
+// }
+
+bool ossimPlanetLandReaderWriter::extractValues(const std::string& filename,
+ ossim_uint32 &level,
+ ossim_uint32 &row,
+ ossim_uint32 &col,
+ ossim_uint32 &id,
+ ossimPlanetLandReaderWriterGeomType &geomType)const
+{
+ ossimString tempString = filename;
+ tempString = tempString.substitute("_", "\n", true);
+
+ std::istringstream in(tempString);
+ ossim_uint32 numberOfValuesFound = 0;
+ geomType = ossimPlanetLandReaderWriterGeomType_NONE;
+ while(!in.fail())
+ {
+ ossimString tempLine;
+
+ std::getline(in, tempLine.string());
+ tempLine = tempLine.upcase();
+ if (tempLine.begin() == tempLine.end()) continue;
+
+ if(tempLine == "TEXTURE")
+ {
+ geomType = (ossimPlanetLandReaderWriterGeomType)(geomType | ossimPlanetLandReaderWriterGeomType_TEXTURE);
+ }
+ else if(tempLine == "GEOM")
+ {
+ geomType = (ossimPlanetLandReaderWriterGeomType)(geomType | ossimPlanetLandReaderWriterGeomType_GEOM);
+ }
+ else if((*tempLine.begin()) == 'L')
+ {
+ tempLine = tempLine.substitute("L", "");
+ level = tempLine.toUInt32();
+ ++numberOfValuesFound;
+ }
+ else if((*tempLine.begin()) == 'Y')
+ {
+ tempLine = tempLine.substitute("Y", "");
+ row = tempLine.toUInt32();
+ ++numberOfValuesFound;
+ }
+ else if((*tempLine.begin()) == 'X')
+ {
+ tempLine = tempLine.substitute("X", "");
+ col = tempLine.toUInt32();
+ ++numberOfValuesFound;
+ }
+ else if(((*tempLine.begin()) == 'I')&&
+ ((*(tempLine.begin()+1)) == 'D'))
+ {
+ tempLine = tempLine.substitute("ID", "");
+ id = tempLine.toUInt32();
+ ++numberOfValuesFound;
+ }
+ }
+ if(!geomType)
+ {
+ geomType = ossimPlanetLandReaderWriterGeomType_LOD;
+ }
+ return (numberOfValuesFound == 4);
+}
+
+std::string ossimPlanetLandReaderWriter::createDbString(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col)const
+{
+ std::stringstream out;
+
+ out << "L"<<level<<"_X"<<col<<"_Y"<<row<<"_ID"<<theId;
+
+ return out.str();
+}
+
+#if 0
+void ossimPlanetLandReaderWriter::setLandType(ossimPlanetLandType landType)
+{
+ theLandType = landType;
+ switch(theLandType)
+ {
+ case ossimPlanetLandType_NORMALIZED_ELLIPSOID:
+ {
+ theModel = new ossimPlanetNormalizedEllipsoidModel;
+ break;
+ }
+ case ossimPlanetLandType_ELLIPSOID:
+ {
+ theModel = new ossimPlanetEllipsoidModel;
+ break;
+ }
+#if 0
+ case ossimPlanetLandType_FLAT:
+ {
+ osg::ref_ptr<ossimPlanetFlatLandModel> theFlatLandModel = new ossimPlanetFlatLandModel;
+ theModel = theFlatLandModel.get();
+ theFlatLandModel->changeNormalModel(new ossimPlanetNormalizedEllipsoidLandModel);
+
+ break;
+ }
+ case ossimPlanetLandType_ORTHOFLAT:
+ {
+ setElevationEnabledFlag(false);
+ osg::ref_ptr<ossimPlanetFlatLandModel> theFlatLandModel = new ossimPlanetFlatLandModel;
+ theModel = theFlatLandModel.get();
+ theFlatLandModel->changeNormalModel(new ossimPlanetNormalizedEllipsoidLandModel);
+ break;
+ }
+#endif
+ default:
+ {
+ break;
+ }
+ }
+}
+#endif
+
+void ossimPlanetLandReaderWriter::setModel(ossimPlanetGeoRefModel* geoModel)
+{
+ theModel = geoModel;
+}
+
+void ossimPlanetLandReaderWriter::setLandNodeCullCallback(ossimPlanetLandCullCallback* callback)
+{
+ theCullNodeCallback = callback;
+}
+
+bool ossimPlanetLandReaderWriter::getElevationEnabledFlag()const
+{
+ return theElevationEnabledFlag;
+}
+
+void ossimPlanetLandReaderWriter::setElevationEnabledFlag(bool elevationFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theElevationEnabledFlag = elevationFlag;
+
+}
+
+ossim_float64 ossimPlanetLandReaderWriter::getHeightExag()const
+{
+ return theHeightExag;
+}
+
+void ossimPlanetLandReaderWriter::setHeightExag(ossim_float64 exag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theHeightExag = exag;
+}
+
+
+ossim_uint32 ossimPlanetLandReaderWriter::getElevationPatchSize()const
+{
+ return theElevationPatchSize;
+}
+
+void ossimPlanetLandReaderWriter::setElevationPatchSize(ossim_uint32 patchSize)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theElevationPatchSize = patchSize;
+ if(!(theElevationPatchSize&1))
+ {
+ theElevationPatchSize += 1;
+ }
+
+}
+
+
+ossim_uint32 ossimPlanetLandReaderWriter::getMaxLevelDetail()const
+{
+ return theMaxLevelDetail;
+}
+
+void ossimPlanetLandReaderWriter::setMaxLevelDetail(ossim_uint32 maxLevelDetail)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theMaxLevelDetail = maxLevelDetail;
+}
+
+ossimFilename ossimPlanetLandReaderWriter::getElevationCacheDir()const
+{
+ return theElevationCacheDir;
+}
+
+
+void ossimPlanetLandReaderWriter::setElevationCacheDir(const ossimFilename& cacheDir)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theElevationCacheDir = cacheDir;
+}
+
+void ossimPlanetLandReaderWriter::setGridUtility(ossimPlanetGridUtility* grid)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theGrid = grid;
+}
+
+const ossimPlanetGridUtility* ossimPlanetLandReaderWriter::gridUtility()const
+{
+ return theGrid.get();
+}
+
+void ossimPlanetLandReaderWriter::setReferenceLayer(osg::ref_ptr<ossimPlanetTextureLayerGroup> reference)
+{
+ theReferenceLayer = reference;
+}
+
+void ossimPlanetLandReaderWriter::setOverlayLayers(osg::ref_ptr<ossimPlanetTextureLayerGroup> overlays)
+{
+ theOverlayLayers = overlays;
+}
+
+void ossimPlanetLandReaderWriter::setMipMappingFlag(bool flag)
+{
+ theMipMappingFlag = flag;
+}
+
+bool ossimPlanetLandReaderWriter::getMipMappingFlag()const
+{
+ return theMipMappingFlag;
+}
+
+void ossimPlanetLandReaderWriter::setMultiTextureEnableFlag(bool flag)
+{
+ theMultiTextureEnableFlag = flag;
+}
+
+bool ossimPlanetLandReaderWriter::getMultiTextureEnableFlag()const
+{
+ return theMultiTextureEnableFlag;
+}
+
+void ossimPlanetLandReaderWriter::setLandCache(osg::ref_ptr<ossimPlanetLandCache> landCache)
+{
+ theLandCache = landCache.get();
+}
+
+void ossimPlanetLandReaderWriter::setElevationDatabase(osg::ref_ptr<ossimPlanetElevationDatabaseGroup> databaseGroup)
+{
+ theElevationDatabase = databaseGroup.get();
+}
+
+osg::ref_ptr<ossimPlanetElevationDatabaseGroup> ossimPlanetLandReaderWriter::getElevationGroup()
+{
+ return theElevationDatabase.get();
+}
+
+const osg::ref_ptr<ossimPlanetElevationDatabaseGroup> ossimPlanetLandReaderWriter::getElevationGroup()const
+{
+ return theElevationDatabase.get();
+}
+
+
+void ossimPlanetLandReaderWriter::newTexture(std::vector<osg::ref_ptr<osg::Texture2D> >& textureList,
+ ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ ossimPlanetImage::ossimPlanetImageStateType& textureState)const
+{
+ osg::ref_ptr<ossimPlanetLandCacheNode> cacheNode;
+ if(theLandCache.valid())
+ {
+ cacheNode = theLandCache->getNode(theGrid->getId(level, row, col), true);
+ }
+ textureList.clear();
+ osg::ref_ptr<ossimPlanetTextureLayer> currentLayer = theReferenceLayer.get();
+ if(!currentLayer.valid()) return;
+ ossim_uint32 size = theOverlayLayers.valid()?theOverlayLayers->numberOfLayers():0;
+ if(!theMultiTextureEnableFlag) size = 0;
+ ossim_uint32 idx = 0;
+// for(idx = 0; idx < size; ++idx)
+ do
+ {
+ osg::ref_ptr<ossimPlanetImage> planetTexture;
+ if(cacheNode.valid()&&cacheNode->getTexture(idx))
+ {
+// std::cout << "IN CACHE!" << std::endl;
+ planetTexture = cacheNode->getTexture(idx);
+ }
+ else
+ {
+// std::cout << "NOT IN CACHE!" << std::endl;
+ planetTexture = currentLayer->getTexture(level, row, col, *theGrid);
+ }
+ if(!planetTexture.valid())
+ {
+ if(!theBlankTexture.valid())
+ {
+ ossim_uint32 w=256, h=256;
+ osg::ref_ptr<ossimPlanetImage> tempImage = new ossimPlanetImage;
+ osg::Image::AllocationMode allocMode = osg::Image::USE_NEW_DELETE;
+ ossim_uint32 sizeInBytes = w*h*4;
+ unsigned char *buf = new unsigned char[sizeInBytes];
+ memset(buf, 0, sizeInBytes);
+ tempImage->setImage(w, h, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, buf, allocMode);
+ theBlankTexture = new ossimPlanetTexture2D;
+ theBlankTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
+ theBlankTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
+ theBlankTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ theBlankTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ theBlankTexture->setDataVariance(osg::Object::STATIC);
+ theBlankTexture->setImage(planetTexture.get());
+ theBlankTexture->setUnRefImageDataAfterApply(false);
+ }
+ textureList.push_back(theBlankTexture.get());
+ }
+ else if(planetTexture.valid())
+// if(planetTexture.valid())
+ {
+ //planetTexture->scaleImage(planetTexture->s(),planetTexture->t(),planetTexture->r(),GL_UNSIGNED_SHORT_5_6_5);
+ osg::ref_ptr<ossimPlanetTexture2D> tempGlTexture= new ossimPlanetTexture2D;
+ if(theMipMappingFlag)
+ {
+ tempGlTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR_MIPMAP_LINEAR);
+ }
+ else
+ {
+ tempGlTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
+ }
+ tempGlTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
+ tempGlTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ tempGlTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ tempGlTexture->setDataVariance(osg::Object::STATIC);
+
+
+ tempGlTexture->setImage(planetTexture.get());
+ tempGlTexture->setUnRefImageDataAfterApply(true);
+#if defined(OSSIMPLANET_USE_DXT1)
+ tempGlTexture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT1_COMPRESSION);
+#elif defined(OSSIMPLANET_USE_DXT3)
+ tempGlTexture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT3_COMPRESSION);
+#elif defined(OSSIMPLANET_USE_DXT5)
+ tempGlTexture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
+#endif
+ textureList.push_back(tempGlTexture.get());
+ }
+ if(idx < size)
+ {
+ currentLayer = theOverlayLayers->layer(idx);
+ ++idx;
+ }
+ else
+ {
+ currentLayer = 0;
+ }
+ }while(currentLayer.valid());
+}
+
+osg::ref_ptr<osg::MatrixTransform> ossimPlanetLandReaderWriter::newGeometry(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
+ osg::ref_ptr<ossimPlanetImage> elevationGrid,
+ ossimPlanetBoundingBox& box,
+ bool& useClusterCullingCallback,
+ osg::Vec3d& clusterControlPoint,
+ osg::Vec3d& clusterCenterNormal,
+ double& minDotProduct,
+ double& maxClusterCullingRadius)const
+{
+// double minLat;
+// double minLon;
+// double maxLat;
+// double maxLon;
+// theGrid->getLatLonBounds(level,
+// row, // row
+// col, // col
+// minLat,
+// minLon,
+// maxLat,
+// maxLon);
+ osg::ref_ptr<osg::Vec3Array> verts = new osg::Vec3Array;
+ osg::ref_ptr<osg::Vec3Array> norms = new osg::Vec3Array;
+ osg::ref_ptr<osg::Vec2Array> tcoords = new osg::Vec2Array;
+// double minLat, minLon;
+// double maxLat, maxLon;
+// unsigned int tempIdx = 0;
+// double x, y, z;
+
+ osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
+
+ osg::ref_ptr<osg::MatrixTransform> matrixTransform = new osg::MatrixTransform;
+ osg::Matrixd localToWorld;
+ osg::Matrixd worldToLocal;
+
+
+
+// matrixTransform->setMatrix(localToWorld);
+// worldToLocal = matrixTransform->getInverseMatrix();
+
+ createPoints(level,
+ row,
+ col,
+ elevationGrid,
+ verts.get(),
+ norms.get(),
+ tcoords.get(),
+ localToWorld,
+ box,
+ useClusterCullingCallback,
+ clusterControlPoint,
+ clusterCenterNormal,
+ minDotProduct,
+ maxClusterCullingRadius);
+
+ matrixTransform->setMatrix(localToWorld);
+ worldToLocal = matrixTransform->getInverseMatrix();
+
+ osg::ref_ptr<osg::UIntArray> vindices = new osg::UIntArray;
+ ossim_uint32 numColumns = (theElevationPatchSize);
+ ossim_uint32 numRows = numColumns;
+
+ ossim_uint32 c = 0, ei=0;
+#if 1
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES));
+ osg::Geometry::PrimitiveSetList primSetList;
+ ossim_uint32 i = 0;
+ ossim_uint32 j = 0;
+ for(i = 1; i < numRows;i+=2)
+ {
+ for(j = 1; j < numColumns;j+=2)
+ {
+ ossim_uint32 i00 = (i)*numColumns + j;
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numColumns+1));
+ drawElements.push_back(i00 - (numColumns));
+
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numColumns));
+ drawElements.push_back(i00 - (numColumns-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numColumns-1));
+ drawElements.push_back(i00 + 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + 1);
+ drawElements.push_back(i00 + (numColumns+1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numColumns+1));
+ drawElements.push_back(i00 + (numColumns));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numColumns));
+ drawElements.push_back(i00 + (numColumns-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numColumns-1));
+ drawElements.push_back(i00 - 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - 1);
+ drawElements.push_back(i00 - (numColumns+1));
+ }
+ }
+ primSetList.push_back(&drawElements);
+ geom->setPrimitiveSetList(primSetList);
+ //smoothGeometry();
+#endif
+#if 0
+
+ osg::Geometry::PrimitiveSetList primSetList;// ( numRows>>1*numCols>>1 );
+ ossim_uint32 i = 0;
+ ossim_uint32 j = 0;
+ for(i = 1; i < numRows;i+=2)
+ {
+ for(j = 1; j < numColumns;j+=2)
+ {
+ ossim_uint32 i00 = (i)*numColumns + j;
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_FAN));
+#if 0
+ drawElements.push_back(i00);
+
+ drawElements.push_back(i00 - (numColumns+1));
+ drawElements.push_back(i00 - (numColumns-1));
+
+ drawElements.push_back(i00 + (numColumns+1));
+ drawElements.push_back(i00 + (numColumns-1));
+
+ drawElements.push_back(i00 - (numColumns+1));
+#endif
+#if 1
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numColumns+1));
+ drawElements.push_back(i00 - (numColumns));
+ drawElements.push_back(i00 - (numColumns-1));
+
+ drawElements.push_back(i00 + 1);
+
+ drawElements.push_back(i00 + (numColumns+1));
+ drawElements.push_back(i00 + (numColumns));
+ drawElements.push_back(i00 + (numColumns-1));
+
+ drawElements.push_back(i00 - 1);
+
+ drawElements.push_back(i00 - (numColumns+1));
+#endif
+ primSetList.push_back(&drawElements);
+ }
+ }
+
+ geom->setPrimitiveSetList(primSetList);
+#endif
+#if 0
+ osg::Geometry::PrimitiveSetList primSetList;// ( numColumns - 1 );
+ //unsigned int length ( 2 * numRows );
+ ossim_uint32 elementIdx = 0;
+ unsigned int i,j;
+ for (i = 0; i < numRows-1; ++i )
+ {
+ elementIdx = 0;
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP));
+ // Loop through all the columns.
+ for (j = 0; j < numColumns; ++j )
+ {
+ unsigned short i10 = (i+1)*(numColumns)+j;
+ unsigned short i00 = (i)*(numColumns)+j;
+ drawElements.push_back(i10);
+ drawElements.push_back(i00);
+ }
+
+ // Define the primitive.
+ primSetList.push_back(&drawElements);
+ }
+ geom->setPrimitiveSetList(primSetList);
+#endif
+ geom->setVertexArray(verts.get());
+ geom->setNormalArray(norms.get());
+ geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+ osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
+ color->push_back(osg::Vec4(1.0,
+ 1.0,
+ 1.0,
+ 1.0));
+ geom->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geom->setColorArray(color.get());
+
+ osgUtil::SmoothingVisitor sv;
+ sv.smooth(*geom); // this will replace the normal vector with a new one
+
+ // now we have to reassign the normals back to the orignal pointer.
+ norms = dynamic_cast<osg::Vec3Array*>(geom->getNormalArray());
+
+ if(theLandType != ossimPlanetLandType_ORTHOFLAT)
+ {
+ unsigned int numPointsInBody = numColumns*numRows;
+ unsigned int numVerticesInSkirt = numColumns*2 + numRows*2;
+
+ // top strip
+ osg::DrawElementsUShort& drawElementsQuad = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,
+ 2*numVerticesInSkirt));
+// 2*numVerticesInSkirt+2));
+ geom->addPrimitiveSet(&drawElementsQuad);
+ ei=0;
+// int firstSkirtVertexIndex = numPointsInBody;
+ osgUtil::Simplifier::IndexList pointsToProtectDuringSimplification;
+
+// bool topPoleFlag = ((90.0 - std::abs(maxLat) ) <= DBL_EPSILON)&&(level > 4);
+// bool bottomPoleFlag = ((90.0 - std::abs(minLat) ) <= DBL_EPSILON)&&(level > 4);
+ // do top skirt
+ //
+ // for(c=0;c<numColumns-1;++c)
+ for(c=0;c<numColumns-1;++c)
+ {
+ unsigned short i0 = c;
+ unsigned short i1 = numPointsInBody + c;
+ drawElementsQuad[ei++] = i0;
+ drawElementsQuad[ei++] = i1;
+// if(!topPoleFlag)
+ {
+ pointsToProtectDuringSimplification.push_back(i0);
+ pointsToProtectDuringSimplification.push_back(i1);
+ }
+ }
+ // do right skirt
+ ossim_uint32 startInteriorIdx = numColumns-1;
+ ossim_uint32 startSkirtIdx = numPointsInBody + numColumns;
+ for(c=0;c<numRows;++c)
+ {
+ unsigned short i0 = startInteriorIdx + numColumns*c;
+ unsigned short i1 = startSkirtIdx + c;
+ {
+ drawElementsQuad[ei++] = i0;
+ drawElementsQuad[ei++] = i1;
+ }
+ pointsToProtectDuringSimplification.push_back(i0);
+ pointsToProtectDuringSimplification.push_back(i1);
+ }
+
+ startInteriorIdx = (numRows-1)*numColumns + (numColumns-1);
+ startSkirtIdx = numPointsInBody + numColumns + numRows;
+ // do bottom skirt
+ //
+ for(c=0;c<numColumns;++c)
+ {
+ unsigned short i0 = startInteriorIdx - c;
+ unsigned short i1 = startSkirtIdx + c;
+ drawElementsQuad[ei++] = i0;
+ drawElementsQuad[ei++] = i1;
+// if(!bottomPoleFlag)
+ {
+ pointsToProtectDuringSimplification.push_back(i0);
+ pointsToProtectDuringSimplification.push_back(i1);
+ }
+ }
+
+ // do left skirt
+ startInteriorIdx = numRows*(numColumns-1);
+ startSkirtIdx = numPointsInBody + 2*numColumns + numRows;
+
+ for(c=0;c<numRows;++c)
+ {
+ unsigned short i0 = startInteriorIdx - numColumns*c;
+ unsigned short i1 = startSkirtIdx + c;
+ drawElementsQuad[ei++] = i0;
+ drawElementsQuad[ei++] = i1;
+ pointsToProtectDuringSimplification.push_back(i0);
+ pointsToProtectDuringSimplification.push_back(i1);
+ }
+ }
+
+// unsigned int numVerticesInBody = numColumns*numRows;
+// unsigned int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0;
+// unsigned int numVertices = numVerticesInBody+numVerticesInSkirt;
+// unsigned int numVertices = numVerticesInBody;
+#if 0
+ unsigned int numVerticesInBody = numColumns*numRows;
+// unsigned int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0;
+// unsigned int numVertices = numVerticesInBody+numVerticesInSkirt;
+ unsigned int numVertices = numVerticesInBody;
+
+
+ if (norms.valid() && norms->size()!=numVertices) norms->resize(numVertices);
+#endif
+ osg::ref_ptr<osg::StateSet> dstate = geom->getOrCreateStateSet();
+ osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace;
+
+
+
+ dstate->setAttributeAndModes(cullFace.get(),
+ osg::StateAttribute::ON);
+
+ if(textures.size())
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < textures.size(); ++idx)
+ {
+ if(textures[idx].valid())
+ {
+ dstate->setTextureAttributeAndModes(idx, textures[idx].get(),
+ osg::StateAttribute::ON);
+ }
+ }
+ }
+// else if(textures.size())
+// {
+// dstate->setTextureAttributeAndModes(idx, textures[0].get(),
+// osg::StateAttribute::ON);
+
+// }
+// geom->setVertexArray(verts.get());
+// geom->setNormalArray(norms.get());
+// geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+
+
+ geom->setTexCoordArray( 0, tcoords.get());
+ geom->setSupportsDisplayList(false);
+
+#if 0 // simplifier
+// unsigned int targetMaxNumVertices = numVertices-1;
+// float sample_ratio = (numVertices <= targetMaxNumVertices) ? 1.0f : (float)targetMaxNumVertices/(float)numVertices;
+// if(topPoleFlag||bottomPoleFlag)
+ {
+ float sample_ratio = .5;
+ osgUtil::Simplifier simplifier(sample_ratio,
+ (geom->getBound().radius());///theModel->getNormalizationScale()));
+
+ simplifier.setDoTriStrip(false);
+ simplifier.setSmoothing(false);
+
+// simplifier.simplify(*geom, pointsToProtectDuringSimplification); // this will replace the normal vector with a new one
+ simplifier.simplify(*geom,pointsToProtectDuringSimplification); // this will replace the normal vector with a new one
+ }
+#endif
+// osgUtil::TriStripVisitor tsv;
+// tsv.setMinStripSize(3);
+// tsv.stripify(*geom);
+
+ osg::ref_ptr<osg::Geode> geode = new osg::Geode;
+// osgUtil::TriStripVisitor v;
+
+// v.apply(*geode.get());
+// osgUtil::SmoothingVisitor::smooth(*(geom.get()));
+ matrixTransform->addChild(geode.get());
+ geode->addDrawable(geom.get());
+ geom->setUseVertexBufferObjects(true);
+ //geom->setFastPathHint(true);
+ // geom->setUseDisplayList(false);
+ matrixTransform->dirtyBound();
+ geom->dirtyBound();
+ matrixTransform->getBound();
+ geom->getBound();
+
+ return matrixTransform;
+}
+void ossimPlanetLandReaderWriter::createPoints(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ osg::ref_ptr<ossimPlanetImage> elevationGrid,
+ osg::Vec3Array *verts,
+ osg::Vec3Array *norms,
+ osg::Vec2Array *tcoords,
+ osg::Matrixd& localToWorld,
+ ossimPlanetBoundingBox& box,
+ bool& useClusterCullingCallback,
+ osg::Vec3d& clusterControlPoint,
+ osg::Vec3d& clusterCenterNormal,
+ double& minDotProduct,
+ double& maxClusterCullingRadius)const
+{
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ ossim_uint32 rows = theElevationPatchSize;
+ ossim_uint32 cols = rows;
+
+ theGrid->createGridPoints(points,
+ level,
+ row,
+ col,
+ rows,
+ cols);
+
+ osg::Vec3d centerPoint;
+ osg::Vec3d centerNormal;
+ ossim_float32* grid = 0;
+ ossim_uint32 idx = 0;
+ osg::Vec3d ul;
+ osg::Vec3d lr;
+ osg::Vec3d ur;
+ osg::Vec3d ll;
+ osg::Vec3d upAxis;
+ osg::Vec3d rightAxis;
+ osg::Vec3d norm1, norm2;
+ osg::Matrixd inverseLocalToWorld;
+ ossim_uint32 numberOfPoints = points.size();
+ if(elevationGrid.valid())
+ {
+ grid = (ossim_float32*)elevationGrid->data();
+ }
+
+// if(grid)
+// {
+// for(idx = 0; idx < numberOfPoints; ++idx)
+// {
+// (*grid) *= theHeightExag;
+// ++grid;
+// }
+// }
+ if(elevationGrid.valid())
+ {
+ grid = (ossim_float32*)elevationGrid->data();
+ }
+
+ ossimPlanetGridUtility::GridPoint centerGridPoint;
+
+ theGrid->getCenterGridPoint(centerGridPoint, level, row, col);
+
+ theGrid->getLatLon(centerPoint, centerGridPoint);
+ theGrid->getLatLon(ul, points[0]);
+ theGrid->getLatLon(ur, points[cols-1]);
+ theGrid->getLatLon(lr, points[points.size()-1]);
+ theGrid->getLatLon(ll, points[(rows-1)*cols]);
+#if 1
+ osg::Matrixd lsrMatrix;
+ theModel->lsrMatrix(centerPoint,
+ lsrMatrix);
+ localToWorld = lsrMatrix;
+ centerNormal = osg::Vec3d(lsrMatrix(2, 0),
+ lsrMatrix(2, 1),
+ lsrMatrix(2, 2));
+ rightAxis = osg::Vec3d(lsrMatrix(0, 0),
+ lsrMatrix(0, 1),
+ lsrMatrix(0, 2));
+ upAxis = osg::Vec3d(lsrMatrix(1, 0),
+ lsrMatrix(1, 1),
+ lsrMatrix(1, 2));
+#endif
+// theModel->lsrMatrix(centerPoint, localToWorld);
+ theModel->forward(osg::Vec3d(centerPoint),
+ centerPoint);
+ theModel->forward(osg::Vec3d(ul),
+ ul);
+ theModel->forward(osg::Vec3d(ur),
+ ur);
+ theModel->forward(osg::Vec3d(lr),
+ lr);
+ theModel->forward(osg::Vec3d(ll),
+ ll);
+
+// theModel->computeLocalToWorldTransform(centerPoint, localToWorld);
+ inverseLocalToWorld.invert(localToWorld);
+
+
+ osg::Vec2d normalDistance(0.0,0.0);
+ osg::Vec2d rightDistance(0.0,0.0);
+ osg::Vec2d upDistance(0.0,0.0);
+
+ double h = 0.0;
+ osg::Vec3d groundPlaneNormal = centerNormal;
+ osg::Vec3d groundPlaneCenter = centerPoint;
+ osg::Vec3d p1;
+ double minDelta = 0.0, maxDelta = 0.0;
+ useClusterCullingCallback = level > 0;
+ minDotProduct = 1.0;
+ double maxClusterCullingHeight = 0.0;
+ maxClusterCullingRadius = 0.0;
+ clusterCenterNormal = centerNormal;
+
+
+ osg::Vec3d latLonPoint;
+ osg::Vec3d deltaP;
+ double upDelta = 0.0;
+ double rightDelta = 0.0;
+ double normDelta = 0.0;
+
+ for(idx = 0; idx < numberOfPoints; ++idx)
+ {
+ tcoords->push_back(osg::Vec2d(points[idx].theLocalGridPoint[ossimPlanetGridUtility::GRIDX],
+ points[idx].theLocalGridPoint[ossimPlanetGridUtility::GRIDY]));
+
+ if(grid)
+ {
+ h = (*grid);//*theHeightExag;
+
+ ++grid;
+ }
+ else
+ {
+ h = 0.0;
+ }
+
+ theGrid->getLatLon(latLonPoint, points[idx]);
+ if(h > maxDelta) maxDelta = h;
+ if(h < minDelta) minDelta = h;
+ latLonPoint[ossimPlanetGridUtility::HGT] = h;
+ h /= theModel->getNormalizationScale();
+ theModel->forward(latLonPoint, p1);
+
+ deltaP = (p1-groundPlaneCenter);
+ upDelta = deltaP*upAxis;
+ rightDelta = deltaP*rightAxis;
+ normDelta = deltaP*groundPlaneNormal;
+
+ if(normDelta < normalDistance[1]) normalDistance[1] = normDelta;
+ if(normDelta > normalDistance[0]) normalDistance[0] = normDelta;
+ if(upDelta < upDistance[1]) upDistance[1] = upDelta;
+ if(upDelta > upDistance[0]) upDistance[0] = upDelta;
+ if(rightDelta < rightDistance[1]) rightDistance[1] = rightDelta;
+ if(rightDelta > rightDistance[0]) rightDistance[0] = rightDelta;
+ theModel->normal(p1,
+ norm1);
+
+ double product = deltaP*groundPlaneNormal;
+ if(product > maxDelta) maxDelta = product;
+ if(product < minDelta) minDelta = product;
+
+ if (useClusterCullingCallback)
+ {
+ osg::Vec3 dv = p1 - centerPoint;
+ double d = sqrt(dv.x()*dv.x() + dv.y()*dv.y() + dv.z()*dv.z());
+ double globeRadius = 1.0;
+ double theta = acos( globeRadius/ (globeRadius + fabs(h) ));
+ double phi = 2.0 * asin (d*0.5/globeRadius); // d/globeRadius;
+ double beta = theta+phi;
+ double cutoff = osg::PI_2;
+ //my_notify(osg::INFO)<<"theta="<<theta<<"\tphi="<<phi<<" beta "<<beta<<std::endl;
+ if (phi<cutoff && beta<cutoff)
+ {
+ double localDotProduct = -sin(theta + phi);
+ double localM = globeRadius*( 1.0/ cos(theta+phi) - 1.0);
+ double localRadius = static_cast<float>(globeRadius * tan(beta)); // beta*globeRadius;
+ minDotProduct = osg::minimum(minDotProduct, localDotProduct);
+ maxClusterCullingHeight = osg::maximum(maxClusterCullingHeight,localM);
+ maxClusterCullingRadius = osg::maximum(maxClusterCullingRadius,localRadius);
+ }
+ else
+ {
+ //my_notify(osg::INFO)<<"Turning off cluster culling for wrap around tile."<<std::endl;
+ useClusterCullingCallback = false;
+ }
+ }
+
+ p1 = p1*inverseLocalToWorld;
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ verts->push_back(p1);
+ norms->push_back(norm1);
+ }
+ clusterControlPoint = centerPoint + centerNormal*maxClusterCullingHeight;
+
+ clusterControlPoint = clusterControlPoint*inverseLocalToWorld;
+ clusterCenterNormal = osg::Matrixd::transform3x3(localToWorld,clusterCenterNormal);
+ box.extrude(groundPlaneCenter,
+ upAxis,
+ rightAxis,
+ groundPlaneNormal,
+ upDistance,
+ rightDistance,
+ normalDistance);
+ box.transform(inverseLocalToWorld);
+
+//#if 0
+// ------------------- Now let's do the skirt -------------------------
+
+ ossim_uint32 colIdx = 0;
+ ossim_uint32 rowIdx = 0;
+ if(theLandType != ossimPlanetLandType_ORTHOFLAT)
+ {
+ // top skirt points
+ double scale = .02;
+ double defaultSkirtLength = box.radius()*scale;
+ grid = 0;
+ if(elevationGrid.valid())
+ {
+ grid = (ossim_float32*)elevationGrid->data();
+ }
+ double minHeight = 99999999999.0;
+ double maxDeltaHeight = -999999999999.0, minDeltaHeight = 9999999999999.0;
+ double deltaHeight=defaultSkirtLength;
+ if(grid)
+ {
+ for(colIdx = 0; colIdx < cols; ++colIdx)
+ {
+ if(maxDeltaHeight < *grid) maxDeltaHeight = *grid;
+ if(minDeltaHeight > *grid) minDeltaHeight = *grid;
+// double value = (*grid -defaultSkirtLength)*theHeightExag;
+// if(value < minHeight) minHeight = value;
+ ++grid;
+ }
+ grid = (ossim_float32*)elevationGrid->data();
+ deltaHeight = ossim::max(defaultSkirtLength, ((maxDeltaHeight-minDeltaHeight)));//*theHeightExag));
+ }
+// std::cout << "deltaHeight = " << deltaHeight << "\n";
+// if(elevationGrid.valid())
+// {
+// grid = (ossim_float32*)elevationGrid->data();
+// }
+ for(colIdx = 0; colIdx < cols; ++colIdx)
+ {
+ tcoords->push_back(osg::Vec2d(points[colIdx].theLocalGridPoint[ossimPlanetGridUtility::GRIDX],
+ points[colIdx].theLocalGridPoint[ossimPlanetGridUtility::GRIDY]));
+
+ theGrid->getLatLon(latLonPoint, points[colIdx]);
+ if(grid)
+ {
+// latLonPoint[2] = minHeight;
+ latLonPoint[2] = *grid - deltaHeight;
+ theModel->forward(latLonPoint,
+ p1);
+ ++grid;
+ }
+ else
+ {
+ latLonPoint[2] = -defaultSkirtLength;
+ theModel->forward(latLonPoint,
+ p1);
+ }
+ theModel->normal(p1,
+ norm1);
+ p1 = p1*inverseLocalToWorld;
+
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ verts->push_back(p1);
+ norms->push_back(norm1);
+ }
+ // right skirt
+ maxDeltaHeight = -999999999999.0, minDeltaHeight = 9999999999999.0;
+ if(elevationGrid.valid())
+ {
+ grid = (((ossim_float32*)elevationGrid->data())+(cols-1));
+ }
+ minHeight = 99999999999.0;
+ ossimPlanetGridUtility::GridPoint* pointsPtr = &points.front() + cols;
+ if(grid)
+ {
+ for(rowIdx = 0; rowIdx < rows; ++rowIdx)
+ {
+// double value = (*grid -defaultSkirtLength)*theHeightExag;
+ if(maxDeltaHeight < *grid) maxDeltaHeight = *grid;
+ if(minDeltaHeight > *grid) minDeltaHeight = *grid;
+// if(value < minHeight) minHeight = value;
+ grid+=(cols);
+ }
+ grid = (((ossim_float32*)elevationGrid->data())+(cols-1));
+ deltaHeight = ossim::max(defaultSkirtLength, ((maxDeltaHeight-minDeltaHeight)));//*theHeightExag));
+ }
+
+ pointsPtr = &points.front() + cols-1;
+ for(rowIdx = 0; rowIdx < rows; ++rowIdx)
+ {
+ tcoords->push_back(osg::Vec2d(pointsPtr->theLocalGridPoint[ossimPlanetGridUtility::GRIDX],
+ pointsPtr->theLocalGridPoint[ossimPlanetGridUtility::GRIDY]));
+ theGrid->getLatLon(latLonPoint, *pointsPtr);
+ if(grid)
+ {
+// latLonPoint[2] = minHeight;
+ latLonPoint[2] = *grid - deltaHeight;
+// latLonPoint[2] = (*grid -defaultSkirtLength)*theHeightExag;
+ theModel->forward(latLonPoint,
+ p1);
+ grid+=(cols);
+ }
+ else
+ {
+ theModel->forward(osg::Vec3d(latLonPoint[ossimPlanetGridUtility::LAT],
+ latLonPoint[ossimPlanetGridUtility::LON], -defaultSkirtLength),
+ p1);
+ }
+
+ theModel->normal(p1,
+ norm1);
+ p1 = p1*inverseLocalToWorld;
+
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ verts->push_back(p1);
+ norms->push_back(norm1);
+ pointsPtr += (cols);
+ }
+
+ pointsPtr = &points.front() + (rows)*(cols) - 1;
+
+ // bottom skirt points
+ maxDeltaHeight = -999999999999.0, minDeltaHeight = 9999999999999.0;
+ if(elevationGrid.valid())
+ {
+ grid = (((ossim_float32*)elevationGrid->data())+(((rows)*(cols))-1));
+ }
+ minHeight = 99999999999.0;
+ if(grid)
+ {
+ for(colIdx = 0; colIdx < cols; ++colIdx)
+ {
+// double value = (*grid -defaultSkirtLength)*theHeightExag;
+ if(maxDeltaHeight < *grid) maxDeltaHeight = *grid;
+ if(minDeltaHeight > *grid) minDeltaHeight = *grid;
+// if(value < minHeight) minHeight = value;
+ --grid;
+ }
+ deltaHeight = ossim::max(defaultSkirtLength, ((maxDeltaHeight-minDeltaHeight)));//*theHeightExag));
+ grid = (((ossim_float32*)elevationGrid->data())+(((rows)*(cols))-1));
+ }
+ for(colIdx = 0; colIdx < cols; ++colIdx)
+ {
+ tcoords->push_back(osg::Vec2d(pointsPtr->theLocalGridPoint[ossimPlanetGridUtility::GRIDX],
+ pointsPtr->theLocalGridPoint[ossimPlanetGridUtility::GRIDY]));
+ theGrid->getLatLon(latLonPoint, *pointsPtr);
+ if(grid)
+ {
+// latLonPoint[2] = minHeight;
+ latLonPoint[2] = *grid - deltaHeight;
+ theModel->forward(latLonPoint,
+ p1);
+ --grid;
+ }
+ else
+ {
+ theModel->forward(osg::Vec3d(latLonPoint[ossimPlanetGridUtility::LAT],
+ latLonPoint[ossimPlanetGridUtility::LON],
+ -defaultSkirtLength),
+ p1);
+ }
+
+ theModel->normal(p1,
+ norm1);
+ p1 = p1*inverseLocalToWorld;
+
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ verts->push_back(p1);
+ norms->push_back(norm1);
+ --pointsPtr;
+ }
+
+
+
+ // left skirt
+ maxDeltaHeight = -999999999999.0, minDeltaHeight = 9999999999999.0;
+ grid = 0;
+// pointsPtr = (&points.front() + ((rows)*(cols+1)));
+ pointsPtr = (&points.front() + ((rows-1)*(cols)));
+ if(elevationGrid.valid())
+ {
+ grid = (((ossim_float32*)elevationGrid->data())+((rows-1)*(cols)));
+ }
+ minHeight = 99999999999.0;
+ if(grid)
+ {
+ for(rowIdx = 0; rowIdx < rows; ++rowIdx)
+ {
+ if(maxDeltaHeight < *grid) maxDeltaHeight = *grid;
+ if(minDeltaHeight > *grid) minDeltaHeight = *grid;
+// double value = (*grid -defaultSkirtLength)*theHeightExag;
+// if(value < minHeight) minHeight = value;
+ grid-=(cols);
+ }
+ deltaHeight = ossim::max(defaultSkirtLength, ((maxDeltaHeight-minDeltaHeight)));//*theHeightExag));
+ grid = (((ossim_float32*)elevationGrid->data())+((rows-1)*(cols)));
+ }
+ for(rowIdx = 0; rowIdx < rows; ++rowIdx)
+ {
+ tcoords->push_back(osg::Vec2d(pointsPtr->theLocalGridPoint[ossimPlanetGridUtility::GRIDX],
+ pointsPtr->theLocalGridPoint[ossimPlanetGridUtility::GRIDY]));
+ theGrid->getLatLon(latLonPoint, *pointsPtr);
+ if(grid)
+ {
+ latLonPoint[2] = *grid - deltaHeight;
+ theModel->forward(latLonPoint,
+ p1);
+// grid-=(cols+1);
+ }
+ else
+ {
+ theModel->forward(osg::Vec3d(latLonPoint[0], latLonPoint[1], -defaultSkirtLength),
+ p1);
+ }
+
+ theModel->normal(p1,
+ norm1);
+ p1 = p1*inverseLocalToWorld;
+
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ verts->push_back(p1);
+ norms->push_back(norm1);
+ pointsPtr-=(cols);
+ }
+ }
+//#endif
+}
+
+void ossimPlanetLandReaderWriter::initSupportAttributes(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ osg::Vec3d& centerPoint,
+ osg::Vec3d& ulPoint,
+ osg::Vec3d& urPoint,
+ osg::Vec3d& lrPoint,
+ osg::Vec3d& llPoint,
+ osg::Vec3d& centerNormal,
+ osg::Vec3d& ulNormal,
+ osg::Vec3d& urNormal,
+ osg::Vec3d& lrNormal,
+ osg::Vec3d& llNormal,
+ ossimPlanetBoundingBox& box,
+ std::vector<ossimPlanetBoundingBox>& childrenBounds,
+ const osg::MatrixTransform& transform)const
+{
+ ossimPlanetGridUtility::GridPoint point;
+ osg::Vec3d ul, ur, lr, ll, latLon;
+ theGrid->getLatLonCorners(ul, ur, lr, ll, level, row, col);
+
+// double minLat, minLon, maxLat, maxLon;
+// const osg::Matrixd& worldToLocal = transform.getInverseMatrix();
+// theGrid->getLatLonBounds(level,
+// row,
+// col,
+// minLat,
+// minLon,
+// maxLat,
+// maxLon);
+ theModel->forward(ul,
+ ulPoint);
+
+// lod->theUlPoint = lod->theUlPoint*worldToLocal;
+
+ theModel->forward(ur,
+ urPoint);
+
+// lod->theUrPoint = lod->theUrPoint*worldToLocal;
+
+ theModel->forward(lr,
+ lrPoint);
+// lod->theLrPoint = lod->theLrPoint*worldToLocal;
+
+ theModel->forward(ll,
+ llPoint);
+// lod->theLlPoint = lod->theLlPoint*worldToLocal;
+
+ theGrid->getCenterGridPoint(point,
+ level,
+ row,
+ col);
+ theGrid->getLatLon(latLon,
+ point);
+ theModel->forward(latLon,
+ centerPoint);
+// lod->theCenterPoint = lod->theCenterPoint*worldToLocal;
+
+ theModel->normal(ulPoint,
+ ulNormal);
+// lod->theUlNormal = osg::Matrixd::transform3x3(worldToLocal, lod->theUlNormal);
+
+ theModel->normal(urPoint,
+ urNormal);
+// lod->theUrNormal = osg::Matrixd::transform3x3(worldToLocal, lod->theUrNormal);
+ theModel->normal(lrPoint,
+ lrNormal);
+// lod->theLrNormal = osg::Matrixd::transform3x3(worldToLocal, lod->theLrNormal);
+ theModel->normal(llPoint,
+ llNormal);
+// lod->theLlNormal = osg::Matrixd::transform3x3(worldToLocal, lod->theLlNormal);
+ theModel->normal(centerPoint,
+ centerNormal);
+// lod->theCenterNormal = osg::Matrixd::transform3x3(worldToLocal, lod->theCenterNormal);
+
+ osg::Vec3d center = (ulPoint +
+ urPoint +
+ lrPoint +
+ llPoint)*.25;
+ osg::Vec3d delta = (center-centerPoint);
+ double normalizedMax = (6000.0*theHeightExag);///theModel->getNormalizationScale();
+ double distance = delta.length() + normalizedMax;
+ double distance2 = -distance;
+
+ switch(theLandType)
+ {
+ case ossimPlanetLandType_ORTHOFLAT:
+ case ossimPlanetLandType_FLAT:
+ {
+ distance = 0;
+ distance2 = 0;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ box.extrude(ulPoint,
+ urPoint,
+ lrPoint,
+ llPoint,
+ centerNormal,
+ osg::Vec2d(distance, distance2));
+ childrenBounds.resize(4);
+ ossim_uint32 nextRow = row<<1;
+ ossim_uint32 nextCol = col<<1;
+ createBounds(level+1,
+ nextRow,
+ nextCol,
+ childrenBounds[0],
+ transform);
+ createBounds(level+1,
+ nextRow,
+ nextCol+1,
+ childrenBounds[1],
+ transform);
+ createBounds(level+1,
+ nextRow+1,
+ nextCol+1,
+ childrenBounds[2],
+ transform);
+ createBounds(level+1,
+ nextRow+1,
+ nextCol,
+ childrenBounds[3],
+ transform);
+}
+
+void ossimPlanetLandReaderWriter::createBounds(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ ossimPlanetBoundingBox& bounds,
+ const osg::MatrixTransform& /* transform */ )const
+{
+ osg::Vec3d ulPoint, urPoint, lrPoint, llPoint, centerPoint;
+ osg::Vec3d centerNormal;
+// double minLat, minLon, maxLat, maxLon;
+ osg::Vec3d ul, ur, lr, ll, latLon;
+ ossimPlanetGridUtility::GridPoint point;
+ theGrid->getLatLonCorners(ul, ur, lr, ll, level, row, col);
+// const osg::Matrixd& worldToLocal = transform.getInverseMatrix();
+// theGrid->getLatLonBounds(level,
+// row,
+// col,
+// minLat,
+// minLon,
+// maxLat,
+// maxLon);
+ theModel->forward(ul,
+ ulPoint);
+
+// lod->theUlPoint = lod->theUlPoint*worldToLocal;
+
+ theModel->forward(ur,
+ urPoint);
+
+// lod->theUrPoint = lod->theUrPoint*worldToLocal;
+
+ theModel->forward(lr,
+ lrPoint);
+// lod->theLrPoint = lod->theLrPoint*worldToLocal;
+
+ theModel->forward(ll,
+ llPoint);
+// lod->theLlPoint = lod->theLlPoint*worldToLocal;
+
+ theGrid->getCenterGridPoint(point,
+ level,
+ row,
+ col);
+ theGrid->getLatLon(latLon,
+ point);
+
+ theModel->forward(latLon,
+ centerPoint);
+// lod->theCenterPoint = lod->theCenterPoint*worldToLocal;
+
+ theModel->normal(centerPoint,
+ centerNormal);
+// lod->theCenterNormal = osg::Matrixd::transform3x3(worldToLocal, lod->theCenterNormal);
+
+ osg::Vec3d center = (ulPoint +
+ urPoint +
+ lrPoint +
+ llPoint)*.25;
+ osg::Vec3d delta = (center-centerPoint);
+ double normalizedMax = (6000.0*theHeightExag);///theModel->getNormalizationScale();
+ double distance = delta.length() + normalizedMax;
+ double distance2 = distance;
+
+ switch(theLandType)
+ {
+ case ossimPlanetLandType_ORTHOFLAT:
+ case ossimPlanetLandType_FLAT:
+ {
+ distance = 0;
+ distance2 = 0;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ bounds.extrude(ulPoint,
+ urPoint,
+ lrPoint,
+ llPoint,
+ centerNormal,
+ osg::Vec2d(distance, distance2));
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetLandReaderWriter::newElevation(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const
+{
+ osg::ref_ptr<ossimPlanetImage> grid;
+ osg::ref_ptr<ossimPlanetLandCacheNode> cacheNode;
+
+ if(theLandCache.valid())
+ {
+ cacheNode = theLandCache->getNode(theGrid->getId(level, row, col), true);
+ }
+
+ if(!theElevationEnabledFlag)
+ {
+ return grid;
+ }
+
+ if(cacheNode.valid())
+ {
+ grid = cacheNode->getElevation();
+ }
+ if(grid.valid())
+ {
+ return grid;
+ }
+
+ ossim_uint32 rows = theElevationPatchSize;
+ ossim_uint32 cols = rows;
+ theElevationGrid->setTileWidthHeight(theElevationPatchSize, theElevationPatchSize);
+
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ theElevationGrid->createGridPoints(points,
+ level,
+ row,
+ col,
+ rows,
+ cols);
+ grid = theElevationDatabase->getTexture(level, row, col, *theElevationGrid);
+ if(grid.valid())
+ {
+ ossim_float32* gridPtr = (ossim_float32*)grid->data();
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 area = grid->s()*grid->t();
+ osg::Vec3d latLonPoint;
+ for(;idx < area; ++idx)
+ {
+ theElevationGrid->getLatLon(latLonPoint, points[idx]);
+ double offset = theModel->getGeoidOffset(latLonPoint[0],
+ latLonPoint[1]);
+ if(*gridPtr == OSSIMPLANET_NULL_HEIGHT)
+ {
+ *gridPtr = offset;
+ }
+ else
+ {
+ *gridPtr = (*gridPtr)*theHeightExag + offset;
+ }
+ ++gridPtr;
+ }
+ }
+
+ return grid;
+
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetLandReaderWriter::getCachedElevation(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col)const
+{
+ osg::ref_ptr<ossimPlanetImage> result;
+ std::ostringstream tempStream;
+
+ if(!theElevationEnabledFlag) return result;
+ if(theElevationCacheDir!= "")
+ {
+ tempStream << "L" << level<<"_X"<<col<<"_Y"<<row<<".elev";
+ ossimFilename filename;
+
+ filename = theElevationCacheDir.dirCat(tempStream.str().c_str());
+ if(filename.exists())
+ {
+ ossimEndian endian;
+ std::ifstream inFile(filename.c_str(),std::ios::in|std::ios::binary);
+ ossim_uint8 endianFlag;
+ ossim_uint32 w;
+ ossim_uint32 h;
+ ossimByteOrder byteOrder;
+ if(inFile.good())
+ {
+ inFile.read((char*)(&endianFlag), 1);
+ inFile.read((char*)(&w), 4);
+ inFile.read((char*)(&h), 4);
+
+ byteOrder = (ossimByteOrder)endianFlag;
+ if(endian.getSystemEndianType() != byteOrder)
+ {
+ endian.swap(&w, 4);
+ endian.swap(&h, 4);
+ }
+
+ result = new ossimPlanetImage;
+ result->allocateImage(w, h, 1, GL_LUMINANCE, GL_FLOAT);//new ossimPlanetElevationGrid(w, h);
+ ossim_float32* data = (ossim_float32*)result->data();
+
+ inFile.read((char*)data, w*h*sizeof(ossim_float32));
+
+ if(endian.getSystemEndianType() != byteOrder)
+ {
+ endian.swap(data, w*h);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetLandReaderWriter::writeElevationToCache(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ osg::ref_ptr<ossimPlanetImage> elevation)const
+{
+ if(theElevationCacheDir!= "")
+ {
+ if(theElevationCacheDir.exists())
+ {
+ std::ostringstream tempStream;
+ ossimEndian endian;
+ tempStream << "L" << level<<"_X"<<col<<"_Y"<<row<<".elev";
+ ossimFilename filename;
+ filename = theElevationCacheDir.dirCat(tempStream.str().c_str());
+
+ std::ofstream oFile(filename.c_str(),
+ std::ios::out|std::ios::binary);
+ ossim_uint8 endianType = (ossim_uint8)endian.getSystemEndianType();
+ ossim_uint32 w = elevation->getWidth();
+ ossim_uint32 h = elevation->getHeight();
+ ossim_float32* data = (ossim_float32*)elevation->data();
+ if(oFile.good())
+ {
+ oFile.write((char*)&endianType, 1);
+ oFile.write((char*)&w, 4);
+ oFile.write((char*)&h, 4);
+ oFile.write((char*)data, sizeof(ossim_float32)*w*h);
+ }
+ }
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLatLonHud.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLatLonHud.cpp
new file mode 100644
index 0000000..7a420e6
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLatLonHud.cpp
@@ -0,0 +1,506 @@
+#include <iostream>
+#include <sstream>
+#include <ossimPlanet/ossimPlanetLatLonHud.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <osg/StateSet>
+#include <osg/Matrixd>
+#include <osg/Material>
+#include <osg/Projection>
+#include <osg/MatrixTransform>
+#include <osg/LineWidth>
+#include <osg/PolygonMode>
+#include <osgUtil/CullVisitor>
+#include <osgUtil/IntersectVisitor>
+#include <OpenThreads/ScopedLock>
+#include <ossim/base/ossimDms.h>
+#include <osgGA/EventVisitor>
+
+class ossimPlanetLatLonHudUpdateCallback : public osg::NodeCallback
+{
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ ossimPlanetLatLonHud* n = dynamic_cast<ossimPlanetLatLonHud*>(node);
+ if(n)
+ {
+ if(n->enableFlag())
+ {
+ n->traverse(*nv);
+ }
+ return;
+ }
+ traverse(node, nv);
+ }
+};
+
+ossimPlanetLatLonHud::ossimPlanetLatLonHud()
+{
+ setUpdateCallback(new ossimPlanetLatLonHudUpdateCallback);
+ theInitializedFlag = false;
+ theAutoUpdateFlag = true;
+ theFontName = "arial.ttf";
+ theFont = osgText::readFontFile(theFontName.c_str());
+ theFontChanged = true;
+
+ theCharacterSize = 16;
+ theCharacterSizeDirtyFlag = true;
+ theLookLabel = "Look At: ";
+ theEyeLabel = "Eye: ";
+ theRangeLabel = "Range: ";
+ theLatDisplayString = "dd.ddddddddddddC";
+ theLonDisplayString = "ddd.ddddddddddddC";
+
+ theCompass = new ossimPlanetCompass;
+ theCompass->setRotateByViewMatrix(true);
+ theCompass->buildCompass();
+ theCompass->getOrCreateStateSet()->setAttribute(new osg::PolygonMode(),
+ osg::StateAttribute::PROTECTED); // don't allow to go to wireframe
+
+ theViewportChangedFlag = false;
+}
+
+void ossimPlanetLatLonHud::traverse(osg::NodeVisitor& nv)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(!theEnableFlag) return;
+ bool traverseChildren = theViewport.valid();
+ if(!thePlanet)
+ {
+ thePlanet = ossimPlanet::findPlanet(this);
+ }
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(!theInitializedFlag)
+ {
+ initialize();
+ }
+ if(theViewportChangedFlag&&theViewport.valid())
+ {
+ theCameraNode->setProjectionMatrix(osg::Matrix::ortho2D(theViewport->x(),
+ theViewport->width(),
+ theViewport->y(),
+ theViewport->height()));
+ theViewportChangedFlag = false;
+ setRedrawFlag(true);
+ }
+ if(theAutoUpdateFlag&&thePlanet)
+ {
+ // osg::Vec3d latLonHeight = thePlanet->getLineOfSiteLatLonHeightPoint();
+ // osg::Vec3d nadir = thePlanet->getNadirLatLonHeightPoint();
+
+ // theLatLonHeight[0] = latLonHeight[0];
+ // theLatLonHeight[1] = latLonHeight[1];
+ // theNadirLatLonHeight[0] = nadir[0];
+ // theNadirLatLonHeight[1] = nadir[1];
+ }
+ if(theViewport.valid())
+ {
+ updatePosition();
+ Group::traverse(nv);
+ }
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ if(!theInitializedFlag) return;
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(cullVisitor)
+ {
+ double x = cullVisitor->getViewport()->x();
+ double y = (int)cullVisitor->getViewport()->y();
+ double w = (int)cullVisitor->getViewport()->width();
+ double h = (int)cullVisitor->getViewport()->height();
+ if(!theViewport.valid())
+ {
+ theViewport = new osg::Viewport(x,y,w,h);
+ theViewportChangedFlag = true;
+ }
+ else
+ {
+ if( !ossim::almostEqual(theViewport->x(), x)||
+ !ossim::almostEqual(theViewport->y(), y)||
+ !ossim::almostEqual(theViewport->width(), w)||
+ !ossim::almostEqual(theViewport->height(), h))
+ {
+ theViewport->setViewport(x,y,w,h);
+ setRedrawFlag(true);
+ theViewportChangedFlag = true;
+ }
+ }
+ }
+ if(traverseChildren)
+ {
+ Group::traverse(nv);
+ }
+ break;
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
+ if(ev)
+ {
+ ossimPlanetViewer* viewer = dynamic_cast<ossimPlanetViewer*>(ev->getActionAdapter());
+ if(viewer&&viewer->currentCamera()&&viewer->currentLookAt())
+ {
+ theNadirLatLon[0] = viewer->currentCamera()->lat();
+ theNadirLatLon[1] = viewer->currentCamera()->lon();
+ theNadirLatLon[2] = viewer->currentCamera()->altitude();
+ theAltitude = viewer->currentCamera()->altitude();
+ theLineOfSiteLatLon[0] = viewer->currentLookAt()->lat();
+ theLineOfSiteLatLon[1] = viewer->currentLookAt()->lon();
+ theLineOfSiteLatLon[2] = viewer->currentLookAt()->altitude();
+ if(theModel.valid())
+ {
+ theModel->ellipsoidalToMsl(theNadirLatLon);
+ theModel->ellipsoidalToMsl(theLineOfSiteLatLon);
+ }
+ theRange = viewer->currentLookAt()->range();
+ if(viewer->model())
+ {
+ theAltitude -= viewer->model()->getGeoidOffset(theNadirLatLon[0],theNadirLatLon[1]);
+ }
+ if(theCompass.valid())
+ {
+ theCompass->setHeading(viewer->currentCamera()->heading());
+ theCompass->setPitch(viewer->currentCamera()->pitch());
+ theCompass->setRoll(viewer->currentCamera()->roll());
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void ossimPlanetLatLonHud::initialize()
+{
+ theCrosshairColor = osg::Vec4d(1.0,1.0,1.0,0.6);
+ theTextColor = osg::Vec4d(1.0,1.0,1.0,0.6);
+ theGeode = new osg::Geode();
+ theCrosshair = new osg::Geometry;
+ theCrosshairLineWidth = new osg::LineWidth(3);
+ osg::StateSet* stateset = theGeode->getOrCreateStateSet();
+ stateset->setMode(GL_LIGHTING,
+ osg::StateAttribute::OFF);
+// stateset->setMode(GL_COLOR_MATERIAL,
+// osg::StateAttribute::OFF);
+ stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+ stateset->setRenderBinDetails(11,"RenderBin");
+ stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+ stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ stateset->setAttribute(theCrosshairLineWidth.get(),osg::StateAttribute::ON);
+ stateset->setAttribute(new osg::PolygonMode(),
+ osg::StateAttribute::PROTECTED); // don't allow to go to wireframe
+
+ theLookText = new osgText::Text;
+ theEyeText = new osgText::Text;
+ theRangeText = new osgText::Text;
+
+ theLookText->setBackdropType(osgText::Text::OUTLINE);
+ theEyeText->setBackdropType(osgText::Text::OUTLINE);
+ theRangeText->setBackdropType(osgText::Text::OUTLINE);
+
+
+ theGeode->addDrawable(theLookText.get());
+ theGeode->addDrawable(theEyeText.get());
+ theGeode->addDrawable(theRangeText.get());
+ theGeode->addDrawable(theCrosshair.get());
+
+ theCameraNode = new osg::CameraNode;
+
+// osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
+ theCameraNode->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ theCameraNode->setProjectionMatrix(osg::Matrix::ortho2D(0,1024,0,1024));
+ theCameraNode->setViewMatrix(osg::Matrix::identity());
+ theCameraNode->setClearMask(GL_DEPTH_BUFFER_BIT);
+ theCameraNode->setRenderOrder(osg::CameraNode::POST_RENDER);
+ theCameraNode->addChild(theGeode.get());
+
+// theProjection = new osg::Projection;
+// theProjection->setMatrix(osg::Matrix::ortho2D(0,1024,0,1024));
+// theProjection->addChild(modelview_abs);
+
+
+ addChild(theCameraNode.get());
+
+ theLookText->setSupportsDisplayList(false);
+ theEyeText->setSupportsDisplayList(false);
+ theRangeText->setSupportsDisplayList(false);
+ theCrosshair->setSupportsDisplayList(false);
+
+ theGeode->setStateSet(stateset);
+
+ theCameraNode->addChild(theCompass.get());
+
+
+ theInitializedFlag = true;
+}
+
+void ossimPlanetLatLonHud::updatePosition()
+{
+ char tempBuf[255];
+ if(theCompass.valid())
+ {
+ theCompass->setPosition(osg::Vec3d(theViewport->width()-128,
+ theViewport->height()-128,
+ 0.0));
+ theCompass->setScale(128);
+ // if(thePlanet)
+ // {
+ // theCompass->setHeading(thePlanet->hpr()[0]);
+ // theCompass->setPitch(thePlanet->hpr()[1]);
+ // theCompass->setRoll(thePlanet->hpr()[2]);
+ // }
+ }
+ if(ossim::isnan(theLineOfSiteLatLon[0]) ||
+ ossim::isnan(theLineOfSiteLatLon[1]))
+ {
+ theLookText->setText(theLookLabel + "NaN");
+ // theLonText->setText(theLookLabel + "NaN");
+ }
+ else
+ {
+ ossimDms latDms(theLineOfSiteLatLon[0]);
+ ossimDms lonDms(theLineOfSiteLatLon[1], false);
+ ossimString text = (theLookLabel + latDms.toString(theLatDisplayString.c_str()) + ", "
+ + lonDms.toString(theLonDisplayString.c_str())+ ", "
+ + ossimString::toString(theLineOfSiteLatLon[2]));
+ theLookText->setText(text);
+ }
+ if(ossim::isnan(theNadirLatLon[0]) ||
+ ossim::isnan(theNadirLatLon[1]))
+ {
+ theEyeText->setText(theLookLabel + "NaN");
+ // theLonText->setText(theLookLabel + "NaN");
+ }
+ else
+ {
+ ossimDms latDms(theNadirLatLon[0]);
+ ossimDms lonDms(theNadirLatLon[1], false);
+ ossimString text = (theEyeLabel + latDms.toString(theLatDisplayString.c_str()) + ", "
+ + lonDms.toString(theLonDisplayString.c_str())+ ", "
+ + ossimString::toString(theNadirLatLon[2]));
+ theEyeText->setText(text);
+ }
+ if(!ossim::isnan(theRange))
+ {
+ sprintf(tempBuf,"%lf meters", theRange);
+ theRangeText->setText((theRangeLabel + tempBuf).c_str());
+ }
+ else
+ {
+ sprintf(tempBuf,"%s", "NaN");
+ theRangeText->setText((theRangeLabel + tempBuf).c_str());
+ }
+ if((theFont.valid())&&
+ (theFontChanged))
+ {
+ theLookText->setFont(theFont.get());
+ theEyeText->setFont(theFont.get());
+ theRangeText->setFont(theFont.get());
+
+// theLonText->setFont(theFont.get());
+// theHeightText->setFont(theFont.get());
+// theLineOfSiteText->setFont(theFont.get());
+ theFontChanged = false;
+ }
+ if(theCharacterSizeDirtyFlag)
+ {
+ theLookText->setCharacterSize(theCharacterSize);
+ theEyeText->setCharacterSize(theCharacterSize);
+ theRangeText->setCharacterSize(theCharacterSize);
+// theLonText->setCharacterSize(theCharacterSize);
+// theHeightText->setCharacterSize(theCharacterSize);
+// theLineOfSiteText->setCharacterSize(theCharacterSize);
+// theCharacterSizeDirtyFlag = false;
+ }
+ double ulx = theViewport->x();
+ double uly = theViewport->y();
+ double x = ulx;
+ double y = uly;
+ double w = theViewport->width();
+ double h = theViewport->height();
+
+ osg::BoundingBox bb;
+
+// bb = osg::BoundingBox();
+ osg::Vec3d pos = osg::Vec3d(x, y+5, 0.0);
+// bb.expandBy(theRangeText->getBound());
+ bb = theRangeText->getBound();
+ theRangeText->setPosition(pos);
+ int height = (int)(bb.yMax() - bb.yMin()) + 5;
+ pos += osg::Vec3d(0.0,(height), 0.0);
+ theLookText->setPosition(pos);
+ bb = theLookText->getBound();
+// bb.expandBy(theLookText->getBound());
+ height = (int)(bb.yMax() - bb.yMin()) + 5;
+ pos += osg::Vec3d(0.0,(height), 0.0);
+ theEyeText->setPosition(pos);
+
+ theLookText->setColor(theTextColor);
+ theEyeText->setColor(theTextColor);
+ theRangeText->setColor(theTextColor);
+
+ osg::Vec2Array* vertices = 0;
+ osg::Vec4Array* colorArray = 0;
+ if(!theCrosshair->getVertexArray())
+ {
+ vertices = new osg::Vec2Array;
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ vertices->push_back(osg::Vec2(0.0,0.0));
+ theCrosshair->setVertexArray(vertices);
+ theCrosshair->addPrimitiveSet(new osg::DrawArrays(GL_LINES,0,8));
+ colorArray = new osg::Vec4Array;
+ colorArray->push_back(theCrosshairColor);
+ theCrosshair->setColorArray(colorArray);
+ theCrosshair->setColorBinding(osg::Geometry::BIND_OVERALL);
+ }
+ else
+ {
+ vertices = dynamic_cast<osg::Vec2Array*>(theCrosshair->getVertexArray());
+ colorArray = dynamic_cast<osg::Vec4Array*>(theCrosshair->getColorArray());
+
+ }
+ if(colorArray)
+ {
+ (*colorArray)[0] = theCrosshairColor;
+ }
+ if(vertices)
+ {
+ int centerx = (int)(((double)ulx + (double)w/2));
+ int centery = (int)(((double)uly + (double)h/2));
+
+ (*vertices)[0][0] = centerx - 20;
+ (*vertices)[0][1] = centery;
+ (*vertices)[1][0] = centerx - 5;
+ (*vertices)[1][1] = centery;
+ (*vertices)[2][0] = centerx + 5;
+ (*vertices)[2][1] = centery;
+ (*vertices)[3][0] = centerx + 20;
+ (*vertices)[3][1] = centery;
+
+ (*vertices)[4][0] = centerx;
+ (*vertices)[4][1] = centery + 20;
+ (*vertices)[5][0] = centerx;
+ (*vertices)[5][1] = centery + 5;
+ (*vertices)[6][0] = centerx;
+ (*vertices)[6][1] = centery - 5;
+ (*vertices)[7][0] = centerx;
+ (*vertices)[7][1] = centery - 20;
+ }
+}
+
+osg::Vec4 ossimPlanetLatLonHud::getCrossHairColor()const
+{
+ return theCrosshairColor;
+}
+
+osg::Vec4 ossimPlanetLatLonHud::getTextColor()const
+{
+ return theTextColor;
+}
+
+void ossimPlanetLatLonHud::setCrosshairColor(const osg::Vec4& color)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theCrosshairColor = color;
+}
+
+void ossimPlanetLatLonHud::setFont(const ossimString& fontFile)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theFontChanged = theFontName != fontFile;
+ theFontName = fontFile;
+ theFont = osgText::readFontFile(fontFile.c_str());
+}
+
+void ossimPlanetLatLonHud::setTextColor(const osg::Vec4& color)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theTextColor = color;
+}
+
+void ossimPlanetLatLonHud::setLatDisplayString(const ossimString& latDisplayString)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theLatDisplayString = latDisplayString;
+}
+
+void ossimPlanetLatLonHud::setLonDisplayString(const ossimString& lonDisplayString)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theLonDisplayString = lonDisplayString;
+}
+
+void ossimPlanetLatLonHud::setCharacterSize(float size)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theCharacterSizeDirtyFlag = size != theCharacterSize;
+ theCharacterSize = size;
+
+}
+
+void ossimPlanetLatLonHud::setViewport(osg::ref_ptr<osg::Viewport> viewport)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theViewport = viewport;
+}
+
+void ossimPlanetLatLonHud::setAutoUpdateFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theAutoUpdateFlag = flag;
+}
+
+void ossimPlanetLatLonHud::setCompassTexture(const ossimFilename& compass)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(theCompass.valid())
+ {
+ theCompass->setCompassTexture(compass);
+ theCompass->updateCompass();
+ setRedrawFlag(true);
+ }
+}
+
+#if 0
+void ossimPlanetLatLonHud::setCompassTexture(const ossimFilename& ring,
+ const ossimFilename& interior)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(theCompass.valid())
+ {
+ theCompass->setCompassTexture(ring, interior);
+ theCompass->updateCompass();
+ setRedrawFlag(true);
+ }
+}
+#endif
+
+void ossimPlanetLatLonHud::execute(const ossimPlanetAction& action)
+{
+#if 0
+ if(action.command() == "init")
+ {
+ ossimPlanetLayer::execute(action); // initialize the base.
+ }
+ else
+ {
+ ossimPlanetLayer::execute(action);
+ }
+#endif
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLayer.cpp
new file mode 100644
index 0000000..81e5eac
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLayer.cpp
@@ -0,0 +1,226 @@
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetIdManager.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <osgGA/EventVisitor>
+#include <iostream>
+
+class ossimPlanetLayerFinder : public osg::NodeVisitor
+{
+public:
+ ossimPlanetLayerFinder()
+ :osg::NodeVisitor(NODE_VISITOR,
+ TRAVERSE_ALL_CHILDREN)
+ {
+ thePlanetLayer = 0;
+ }
+
+ virtual void apply(osg::Node& node)
+ {
+ if(!thePlanetLayer)
+ {
+ thePlanetLayer = dynamic_cast<ossimPlanetLayer*>(&node);
+ }
+ else
+ {
+ return;
+ }
+ osg::NodeVisitor::apply(node);
+ }
+
+ ossimPlanetLayer* thePlanetLayer;
+};
+
+class ossimPlanetLayerTraverseCallback : public osg::NodeCallback
+{
+public:
+ ossimPlanetLayerTraverseCallback()
+ {
+ }
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ if(node)
+ {
+ node->traverse(*nv);
+ }
+ }
+};
+
+ossimPlanetLayer::ossimPlanetLayer()
+ :thePlanet(0)
+{
+ setEventCallback(new ossimPlanetTraverseCallback);
+}
+
+ossimPlanetLayer::~ossimPlanetLayer()
+{
+ thePlanet = 0;
+}
+
+void ossimPlanetLayer::traverse(osg::NodeVisitor& nv)
+{
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ if(redrawFlag())
+ {
+ osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
+ if(ev)
+ {
+ if(ev->getActionAdapter())
+ {
+ ev->getActionAdapter()->requestRedraw();
+ setRedrawFlag(false);
+ }
+ }
+ }
+ return;
+ }
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(!thePlanet)
+ {
+ setPlanet(ossimPlanet::findPlanet(this));
+ }
+ break;
+ }
+ default:
+ {
+
+ }
+ }
+ ossimPlanetNode::traverse(nv);
+}
+
+ossimPlanetLayer* ossimPlanetLayer::findLayer(osg::Node* startNode)
+{
+ osg::Node* rootNode = startNode;
+ osg::Node* rootNonNullNode = startNode;
+
+ while(rootNode)
+ {
+ rootNonNullNode = rootNode;
+ ossimPlanetLayer* castNode = dynamic_cast<ossimPlanetLayer*>(rootNode);
+ if(castNode)
+ {
+ return castNode;
+ }
+ if(rootNode->getNumParents() > 0)
+ {
+ rootNode = rootNode->getParent(0);
+ }
+ else
+ {
+ rootNode = 0;
+ }
+ }
+ if(rootNonNullNode)
+ {
+ ossimPlanetLayerFinder finder;
+ rootNonNullNode->accept(finder);
+ return finder.thePlanetLayer;
+ }
+
+ return 0;
+}
+
+ossimPlanetLayer* ossimPlanetLayer::findLayer(osg::NodePath& currentNodePath)
+{
+ if(currentNodePath.empty())
+ {
+ return 0;
+ }
+ for(osg::NodePath::reverse_iterator itr = currentNodePath.rbegin();
+ itr != currentNodePath.rend();
+ ++itr)
+ {
+ ossimPlanetLayer* layer = dynamic_cast<ossimPlanetLayer*>(*itr);
+ if (layer)
+ {
+ return layer;
+ }
+ }
+
+ return 0;
+}
+
+void ossimPlanetLayer::execute(const ossimPlanetAction& action)
+{
+
+#if 0
+ if(action.command() == "setReceiver")
+ {
+ if(action.argCount() == 1)
+ {
+ setPathnameAndRegister(action.arg(1));
+ }
+ }
+ else if(action.command() == "setEnableFlag")
+ {
+ if(action.argCount() == 1)
+ {
+ setEnableFlag(ossimString(action.arg(1)).toBool());
+ }
+ }
+ else if(action.command() == "setId")
+ {
+ if(action.argCount()==1)
+ {
+ setId(action.arg(1));
+ }
+ }
+ else if(action.command() == "setName")
+ {
+ if(action.argCount()==1)
+ {
+ setName(action.arg(1));
+ }
+ }
+ else if(action.command() == "setDescription")
+ {
+ if(action.argCount()==1)
+ {
+ setDescription(action.arg(1));
+ }
+ }
+ else if(action.command() == "init")
+ {
+ if(action.argCount() != 1) return;
+
+ ossimString objectName;
+ ossimString objectArg;
+ ossim_uint32 idx = 1;
+ ossimPlanetAction nestedAction(":dummy dummy " + action.arg(1) );
+ for(idx = 1; idx <= nestedAction.argCount(); ++idx)
+ {
+ if(mkUtils::extractObjectAndArg(objectName,
+ objectArg,
+ nestedAction.arg(idx)))
+ {
+ if(objectName == "Name")
+ {
+ setName(objectArg);
+ }
+ else if(objectName == "Id")
+ {
+ setId(objectArg);
+ }
+ else if(objectName == "Description")
+ {
+ setDescription(objectArg);
+ }
+ else if(objectName == "ReceiverPath")
+ {
+ setPathnameAndRegister(objectArg);
+ }
+ else if(objectName == "Enable")
+ {
+ setEnableFlag(objectArg.toBool());
+ }
+ }
+ }
+ }
+#endif
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLayerFactory.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLayerFactory.cpp
new file mode 100644
index 0000000..5e17b8a
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLayerFactory.cpp
@@ -0,0 +1,63 @@
+#include <ossimPlanet/ossimPlanetLayerFactory.h>
+#include <ossimPlanet/ossimPlanetLayerRegistry.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetLatLonHud.h>
+#include <ossimPlanet/ossimPlanetSousaLayer.h>
+#include <ossimPlanet/ossimPlanetKmlLayer.h>
+#include <ossimPlanet/ossimPlanetAnnotationLayer.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+
+ossimPlanetLayerFactory* ossimPlanetLayerFactory::theInstance = 0;
+
+ossimPlanetLayerFactory::ossimPlanetLayerFactory()
+{
+ theInstance = this;
+}
+
+ossimPlanetLayerFactory::~ossimPlanetLayerFactory()
+{
+ theInstance = 0;
+}
+
+ossimPlanetLayerFactory* ossimPlanetLayerFactory::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetLayerFactory;
+ }
+
+ return theInstance;
+}
+
+ossimPlanetLayer* ossimPlanetLayerFactory::create(const ossimString& type)const
+{
+ if(type == "ossimPlanetLand")
+ {
+ return new ossimPlanetLand;
+ }
+ else if(type == "osismPlanetTerrain")
+ {
+ return new ossimPlanetTerrain;
+ }
+ else if(type == "ossimPlanetVideoLayer")
+ {
+ }
+ else if(type == "ossimPlanetLatLonHud")
+ {
+ return new ossimPlanetLatLonHud;
+ }
+ else if(type == "ossimPlanetSousaLayer")
+ {
+ return new ossimPlanetSousaLayer;
+ }
+ else if(type == "ossimPlanetKmlLayer")
+ {
+ return new ossimPlanetKmlLayer;
+ }
+ else if(type == "ossimPlanetAnnotationLayer")
+ {
+ return new ossimPlanetAnnotationLayer;
+ }
+
+ return 0;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLayerRegistry.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLayerRegistry.cpp
new file mode 100644
index 0000000..0c27acc
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLayerRegistry.cpp
@@ -0,0 +1,89 @@
+#include <ossimPlanet/ossimPlanetLayerRegistry.h>
+#include <ossimPlanet/ossimPlanetLayerFactory.h>
+#include <algorithm>
+ossimPlanetLayerRegistry* ossimPlanetLayerRegistry::theInstance = 0;
+ossimPlanetLayerRegistry::ossimPlanetLayerRegistry()
+{
+ theInstance = this;
+}
+
+ossimPlanetLayerRegistry::~ossimPlanetLayerRegistry()
+{
+ theInstance = 0;
+}
+
+ossimPlanetLayerRegistry* ossimPlanetLayerRegistry::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetLayerRegistry;
+ theInstance->registerFactory(ossimPlanetLayerFactory::instance());
+ }
+
+ return theInstance;
+}
+
+void ossimPlanetLayerRegistry::finalize()
+{
+ if(theInstance)
+ {
+ theFactoryList.clear();
+
+ delete theInstance;
+ theInstance = 0;
+ }
+}
+
+ossimPlanetLayer* ossimPlanetLayerRegistry::create(const ossimString& layerName)const
+{
+ ossimPlanetLayer* result = 0;
+ ossim_uint32 idx = 0;
+ theFactoryListMutex.readLock();
+ for(idx = 0; ((idx < theFactoryList.size())&&(!result)); ++idx)
+ {
+ result = theFactoryList[idx]->create(layerName);
+ }
+ theFactoryListMutex.readUnlock();
+
+ return result;
+}
+
+void ossimPlanetLayerRegistry::registerFactory(ossimPlanetLayerFactoryBase* factory,
+ bool insertFrontFlag)
+{
+ if(!hasFactory(factory))
+ {
+ theFactoryListMutex.writeLock();
+ if(!insertFrontFlag)
+ {
+ theFactoryList.push_back(factory);
+ }
+ else
+ {
+ theFactoryList.insert(theFactoryList.begin(), factory);
+ }
+ theFactoryListMutex.writeUnlock();
+ }
+}
+
+void ossimPlanetLayerRegistry::unregisterFactory(const ossimPlanetLayerFactoryBase* factory)
+{
+ theFactoryListMutex.writeLock();
+ FactoryListType::iterator iter = std::find(theFactoryList.begin(),
+ theFactoryList.end(),
+ factory);
+ if(iter != theFactoryList.end())
+ {
+ theFactoryList.erase(iter);
+ }
+ theFactoryListMutex.writeUnlock();
+}
+
+bool ossimPlanetLayerRegistry::hasFactory(const ossimPlanetLayerFactoryBase* factory)const
+{
+ FactoryListType::const_iterator iter = std::find(theFactoryList.begin(),
+ theFactoryList.end(),
+ factory);
+
+ return (iter!=theFactoryList.end());
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLookAt.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLookAt.cpp
new file mode 100644
index 0000000..94fadf9
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLookAt.cpp
@@ -0,0 +1,48 @@
+#include <ossimPlanet/ossimPlanetLookAt.h>
+
+bool ossimPlanetLookAt::loadXml(ossimRefPtr<ossimXmlNode> xmlNode)
+{
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = xmlNode->getChildNodes();
+ ossim_uint32 idx;
+ ossim_uint32 upper=childNodes.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+
+ if(tag == "latitude")
+ {
+ theLat = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "longitude")
+ {
+ theLon = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "altitude")
+ {
+ theAltitude = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "range")
+ {
+ theRange = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "roll")
+ {
+ theRoll = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "tilt")
+ {
+ thePitch = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "heading")
+ {
+ theHeading = childNodes[idx]->getText().toDouble();
+ }
+ else if(tag == "altitudeMode")
+ {
+ theMode = modeFromString(childNodes[idx]->getText());
+ }
+ }
+
+ return true;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetLsrSpaceTransform.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetLsrSpaceTransform.cpp
new file mode 100644
index 0000000..cc82ad4
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetLsrSpaceTransform.cpp
@@ -0,0 +1,210 @@
+#include <ossimPlanet/ossimPlanetLsrSpaceTransform.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/mkUtils.h>
+#include <osg/io_utils>
+
+ossimPlanetLsrSpaceTransform::ossimPlanetLsrSpaceTransform(ossimPlanetGeoRefModel* model)
+:theModel(model),
+theRedrawFlag(true)
+{
+ theScale[0] = theScale[1] = theScale[2] = 1.0;
+ theHpr[0] = theHpr[1] = theHpr[2] = 0.0;
+ _referenceFrame = RELATIVE_RF;
+}
+
+ossimPlanetLsrSpaceTransform::ossimPlanetLsrSpaceTransform(const ossimPlanetLsrSpaceTransform& src,const osg::CopyOp& copyop)
+:osg::Transform(src, copyop),
+theModel(src.theModel),
+theLatLonAltitude(src.theLatLonAltitude),
+theXYZ(src.theXYZ),
+theHpr(src.theHpr),
+theScale(src.theScale),
+theLocalToWorld(src.theLocalToWorld),
+theInvLocalToWorld(src.theInvLocalToWorld)
+{
+}
+
+void ossimPlanetLsrSpaceTransform::setMatrix(const osg::Matrix& m)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ dirtyBound();
+ theLocalToWorld = m;
+ theInvLocalToWorld.invert(m);
+ matrixToParameters(m);
+}
+
+void ossimPlanetLsrSpaceTransform::setModel(ossimPlanetGeoRefModel* model)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theModel = model;
+ parametersToMatrix();
+ dirtyBound();
+}
+
+void ossimPlanetLsrSpaceTransform::setHeadingPitchRoll(const osg::Vec3d& hpr)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theHpr = hpr;
+ parametersToMatrix();
+ dirtyBound();
+}
+
+void ossimPlanetLsrSpaceTransform::setLatLonAltitude(const osg::Vec3d& value)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theLatLonAltitude = value;
+ parametersToMatrix();
+ dirtyBound();
+}
+
+void ossimPlanetLsrSpaceTransform::setLatLonAltitudeMeanSeaLevel(const osg::Vec3d& value)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theModel.valid())
+ {
+ theLatLonAltitude = value;
+ theModel->mslToEllipsoidal(theLatLonAltitude);
+ }
+ parametersToMatrix();
+ dirtyBound();
+}
+
+void ossimPlanetLsrSpaceTransform::setScale(const osg::Vec3d& value)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theScale = value;
+ parametersToMatrix();
+ dirtyBound();
+}
+
+void ossimPlanetLsrSpaceTransform::setXYZ(const osg::Vec3d& xyz)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theModel.valid())
+ {
+ theXYZ = xyz;
+ theModel->inverse(xyz, theLatLonAltitude);
+ }
+ dirtyBound();
+ parametersToMatrix();
+}
+
+void ossimPlanetLsrSpaceTransform::traverse(osg::NodeVisitor& nv)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(theRedrawFlag)
+ {
+ ossimPlanetNode* node = ossimPlanetNode::findNode(nv.getNodePath());
+ if(node)
+ {
+ node->setRedrawFlag(true);
+ }
+ theRedrawFlag = false;
+ }
+ if(!theModel.valid())
+ {
+ ossimPlanetLayer* layer = ossimPlanetLayer::findLayer(nv.getNodePath());
+ if(layer)
+ {
+ theModel = layer->model();
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ osg::Transform::traverse(nv);
+}
+
+void ossimPlanetLsrSpaceTransform::matrixToParameters(const osg::Matrix& inputM)
+{
+ if(theModel.valid())
+ {
+ osg::Matrixd m;
+ osg::Vec3d translation;
+ osg::Quat rotation;
+ osg::Quat s;
+ // deomcpose some of the parts we need
+ //
+ inputM.decompose(translation, rotation, theScale, s);
+
+ // no solve the relative heading pitch and roll to the
+ // tangent plane at the point translation
+ //
+ theXYZ = translation;
+ theModel->inverse(translation, theLatLonAltitude);
+ theModel->lsrMatrix(theLatLonAltitude, m);//, theOrientationMode);
+ mkUtils::matrixToHpr(theHpr, m, inputM);
+ theRedrawFlag = true;
+ notifyLsrSpaceChanged();
+
+ // std::cout << "hpr = " << theHpr << std::endl;
+// std::cout << "llh = " << theLatLonAltitude << std::endl;
+
+ }
+}
+
+bool ossimPlanetLsrSpaceTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if (_referenceFrame==RELATIVE_RF)
+ {
+ matrix.preMult(theLocalToWorld);
+ }
+ else // absolute
+ {
+ matrix = theLocalToWorld;
+ }
+ return true;
+}
+
+bool ossimPlanetLsrSpaceTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if (_referenceFrame==RELATIVE_RF)
+ {
+ matrix.postMult(theInvLocalToWorld);
+ }
+ else // absolute
+ {
+ matrix = theInvLocalToWorld;
+ }
+ return true;
+}
+
+bool ossimPlanetLsrSpaceTransform::parametersToMatrix()
+{
+ if(theScale.x() == 0.0 || theScale.y() == 0.0 || theScale.z()==0.0) return false;
+ if(!theModel.valid()) return false;
+ osg::Matrixd m;
+ theModel->orientationLsrMatrix(m, theLatLonAltitude, theHpr[0], theHpr[1], theHpr[2]);//, theOrientationMode);
+ theLocalToWorld = osg::Matrixd::scale(osg::Vec3d(theScale[0], theScale[1], theScale[2]))*m;
+ theInvLocalToWorld.invert(theLocalToWorld);
+ theRedrawFlag = true;
+ notifyLsrSpaceChanged();
+ return true;
+}
+
+void ossimPlanetLsrSpaceTransform::notifyLsrSpaceChanged()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->lsrSpaceChanged(this);
+ }
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetManipulator.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetManipulator.cpp
new file mode 100644
index 0000000..e74ac0a
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetManipulator.cpp
@@ -0,0 +1,806 @@
+#include <ossimPlanet/ossimPlanetManipulator.h>
+#include <ossimPlanet/ossimPlanetUtility.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <osg/Quat>
+#include <osg/Notify>
+#include <osgUtil/IntersectVisitor>
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimGpt.h>
+#include <osgUtil/IntersectVisitor>
+#include <ossimPlanet/ossimPlanetInteractionController.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+#include <osg/CoordinateSystemNode>
+#include <OpenThreads/ScopedLock>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+#include <osg/io_utils>
+
+
+#include <iostream>
+
+using namespace osg;
+using namespace osgGA;
+
+ossimPlanetManipulator::ossimPlanetManipulator() :
+ theNavigator(new ossimPlanetNavigator(new ossimPlanetPrimaryBody("earth_wgs84", 6378137.0, 6356752.3142, 86400, 5.9742e24, -180, 180))),
+ theNode(NULL),
+ theEventHandlingFlag(true),
+ theUseFrameEventForUpdateFlag(false),
+ theAutoCalculateIntersectionFlag(true),
+ thePlanet(0),
+ theFusionDistance(1.0)
+{
+// theViewMatrixBuilder = new ossimPlanetViewMatrixBuilder();
+
+theViewMatrixBuilder = new ossimPlanetViewMatrixBuilder(new ossimPlanetEllipsoidModel());
+
+ theFromNodeCallback = new FromNodeCallback(theViewMatrixBuilder.get());
+ theToNodeCallback = new ToNodeCallback(theViewMatrixBuilder.get());
+
+ theNavigator->setUseTimedUpdateFlag(true);
+ initializeDefaultBindings(":navigator");
+}
+
+void ossimPlanetManipulator::initializeDefaultBindings(const ossimString& pathName)
+{
+ setPathnameAndRegister(pathName.c_str());
+
+ // define our valuators
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ iac->defineInteractionValuator("LAT", -1.0f, 1.0f);
+ iac->defineInteractionValuator("LON", -1.0f, 1.0f);
+ iac->defineInteractionValuator("ZOOM", -1.0f, 1.0f);
+ iac->defineInteractionValuator("PITCH", -1.0f, 1.0f);
+ iac->defineInteractionValuator("YAW", -1.0f, 1.0f);
+
+ // initialize bindings
+ // ossimFilename path = ossimEnvironmentUtility::instance()->getUserOssimSupportDir();
+ // path = path.dirCat("planet");
+ // path = path.dirCat("binds.act");
+// if(path.exists())
+// {
+// ossimPlanetActionRouter::instance()->executeFile(path);
+// }
+// else
+ {
+ ossimPlanetDestinationCommandAction(":iac tie x_mouse LON YAW").execute();
+ ossimPlanetDestinationCommandAction(":iac tie y_mouse LAT ZOOM PITCH").execute();
+ ossimPlanetDestinationCommandAction(":iac bind left_mousedown {"+pathName+" rotatestart}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind left_mouseup {"+pathName+" rotatestop}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind middle_mousedown {"+pathName+" losrotatestart}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind middle_mouseup {"+pathName+" losrotatestop}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind right_mousedown {"+pathName+" loszoomstart}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind right_mouseup {"+pathName+" loszoomstop}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind shift_middle_mousedown {"+pathName+" zoomstart}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind shift_middle_mouseup {"+pathName+" zoomstop}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind shift_right_mousedown {"+pathName+" lookstart}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind shift_right_mouseup {"+pathName+" lookstop}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind right_key {"+pathName+" flystart -.015625 0.0}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind left_key {"+pathName+" flystart .015625 0.0}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind up_key {"+pathName+" flystart 0.0 -.015625}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind down_key {"+pathName+" flystart 0.0 .015625}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind u_key {"+pathName+" rotatenorth}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind U_key {"+pathName+" rotatenorthup}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind p_key {"+pathName+" printlatlonelev}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind P_key {"+pathName+" printlookcoordinates}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind z_key {"+pathName+" recordanimation}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind Z_key {"+pathName+" playanimation}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind space_key {"+pathName+" reset}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind return_key {"+pathName+" stop}").execute();
+ ossimPlanetDestinationCommandAction(":iac bind A_key {: manualaction}").execute();
+ }
+}
+
+
+
+void ossimPlanetManipulator::extractLookFromParameters(ossimXmlNode* node,
+ double& lat,
+ double& lon,
+ double& alt,
+ double& h,
+ double& p,
+ double& r)
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = thePlanet->model();
+
+
+
+ ossimString vref = node->getAttributeValue("vref");
+ ossimString value;
+
+
+
+
+ if(node->getChildTextValue(value, "longitude"))
+ {
+ lon = value.toDouble();
+ }
+
+ if(node->getChildTextValue(value, "latitude"))
+ {
+ lat = value.toDouble();
+ }
+
+ if(node->getChildTextValue(value, "altitude"))
+ {
+ alt = value.toDouble();
+ if(node->getChildTextValue(value, "altitudeMode"))
+ {
+ if(value.contains("relative"))
+ {
+ alt += model->getHeightAboveEllipsoid(lat, lon);
+ }
+
+ else if(value.contains("clamp"))
+ {
+ alt = model->getHeightAboveEllipsoid(lat, lon);
+ }
+ else if(value.contains("absolute"))
+ {
+ if(vref!="wgs84")
+ {
+ alt += model->getGeoidOffset(lat, lon);
+ }
+ }
+ }
+ }
+
+ if(node->getChildTextValue(value, "heading"))
+ {
+ h = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "pitch"))
+ {
+ p = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "roll"))
+ {
+ r = value.toDouble();
+ }
+}
+
+
+void ossimPlanetManipulator::execute(const ossimPlanetAction& a)
+{
+
+ //std::cout << "xxxx\n";
+ double lat_ = 0.0, lon_ = 0.0, altitude = 0.0 , heading = 0.0, pitch = 0.0, roll = 0.0;
+ ossimString command = a.command();
+ bool aircraft = false;
+ const ossimPlanetXmlAction* xmlAction = a.toXmlAction();
+ ossimXmlNode* lookFromNode = 0;
+
+ if(xmlAction)
+ {
+ const ossimXmlNode::ChildListType& children = xmlAction->xmlNode()->getChildNodes();
+ if(command == "Set")
+ {
+ ossim_uint32 idx = 0;
+ for(;idx < children.size();++idx)
+ {
+ if(children[idx]->getTag() == "LookFrom")
+ {
+ ossimRefPtr<ossimXmlNode> node = children[idx];
+ lookFromNode = (ossimXmlNode *)node->getChildNodes()[0].get();
+ break;
+ }
+ }
+ }
+ }
+ if(lookFromNode)
+ {
+ extractLookFromParameters(lookFromNode,lat_,lon_,altitude,heading,pitch,roll);
+
+ viewMatrixBuilder()->setLookFrom(osg::Vec3d(lat_, lon_, altitude), osg::Vec3d(heading,pitch, roll), 1);
+ theNavigator->setRedrawFlag(true);
+
+ aircraft = true;
+
+ }
+if(aircraft == false)
+{
+ if(theNavigator.valid())
+ {
+
+ theNavigator->execute(a);
+ }
+}
+}
+ossimPlanetManipulator::~ossimPlanetManipulator()
+{
+}
+
+
+void ossimPlanetManipulator::setNode(osg::Node* node)
+{
+ theNode = node;
+
+ if(theNode.valid())
+ {
+ thePlanet = ossimPlanet::findPlanet(theNode.get());//finder.thePlanet;
+ if(theNavigator.valid())
+ {
+ if(thePlanet)
+ {
+ theViewMatrixBuilder->setGeoRefModel(thePlanet->model().get());
+ }
+ theNavigator->setPlanet(thePlanet);
+ }
+ }
+}
+
+
+const osg::Node* ossimPlanetManipulator::getNode() const
+{
+ return theNode.get();
+}
+
+
+osg::Node* ossimPlanetManipulator::getNode()
+{
+ return theNode.get();
+}
+
+
+void ossimPlanetManipulator::getLatLonHgtHPR(double& lat, double& lon, double& hgt,
+ double& heading, double& pitch, double& roll)const
+{
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ lat = theNavigator->lat();
+ lon = theNavigator->lon();
+ hgt = theNavigator->elev();
+ heading = theNavigator->orientation()[0];
+ pitch = theNavigator->orientation()[1];
+ roll = theNavigator->orientation()[2];
+}
+
+void ossimPlanetManipulator::solveLookAt(double losLat, double losLon, double losHeight,
+ double& heading, double& pitch, double& roll, double& range)const
+
+{
+ theNavigator->solveLookAt(losLat, losLon, losHeight, heading, pitch, roll, range);
+}
+
+void ossimPlanetManipulator::playRecording()
+{
+ theNavigator->playRecording();
+}
+
+void ossimPlanetManipulator::startRecording()
+{
+ theNavigator->startRecording();
+}
+
+void ossimPlanetManipulator::stopRecording()
+{
+ theNavigator->stopRecording();
+}
+
+void ossimPlanetManipulator::saveRecording(std::ostream& out)
+{
+ theNavigator->saveRecording(out);
+}
+
+bool ossimPlanetManipulator::loadRecording(std::istream& in)
+{
+ return theNavigator->loadRecording(in);
+}
+
+void ossimPlanetManipulator::setEventHandlingFlag(bool flag)
+{
+ theEventHandlingFlag = flag;
+}
+
+void ossimPlanetManipulator::setUseFrameEventForUpdateFlag(bool flag)
+{
+ theUseFrameEventForUpdateFlag = flag;
+ if(flag)
+ {
+ theNavigator->setUseTimedUpdateFlag(false);
+ }
+ else
+ {
+ theNavigator->setUseTimedUpdateFlag(true);
+ }
+}
+
+void ossimPlanetManipulator::setAutoCalculateIntersectionFlag(bool flag)
+{
+ theAutoCalculateIntersectionFlag = flag;
+}
+
+void ossimPlanetManipulator::setLosXYZ(const osg::Vec3d& losXYZ)
+{
+ if(theNavigator->canSetLineOfSite())
+ {
+ theNavigator->setLosXYZ(losXYZ);
+ }
+}
+
+void ossimPlanetManipulator::init(const GUIEventAdapter& ,GUIActionAdapter&)
+{
+}
+
+void ossimPlanetManipulator::home(const GUIEventAdapter& ,GUIActionAdapter& us)
+{
+ ossimPlanetDestinationCommandAction(":navigator reset").execute();
+ us.requestRedraw();
+}
+
+bool ossimPlanetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
+{
+ updateViewMatrixNodes();
+ // XXX most of this belongs in ossimPlanetQT.
+ if(!theEventHandlingFlag)
+ {
+ return false;
+ }
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+
+ ossimString modKeyString;
+
+ if(ea.getModKeyMask() & GUIEventAdapter::MODKEY_SHIFT)
+ {
+ modKeyString += "shift_";
+ }
+ if(ea.getModKeyMask() & GUIEventAdapter::MODKEY_CTRL)
+ {
+ modKeyString += "ctrl_";
+ }
+ if(ea.getModKeyMask() & GUIEventAdapter::MODKEY_ALT)
+ {
+ modKeyString += "alt_";
+ }
+ if(ea.getModKeyMask() & GUIEventAdapter::MODKEY_META)
+ {
+ modKeyString += "meta_";
+ }
+ switch(ea.getEventType())
+ {
+ case GUIEventAdapter::FRAME:
+ {
+ osg::Vec3d pt;
+ bool validLos = calculateLineOfSiteLatLonHeight(pt);
+
+ if(validLos)//&&theNavigator->canSetLineOfSite()&&theNavigator->landModel().valid())
+ {
+ osg::Vec3d ptXYZ;
+ theNavigator->landModel()->forward(pt, ptXYZ);
+ theNavigator->setLosXYZ(ptXYZ);
+
+ }
+
+ if(theUseFrameEventForUpdateFlag)
+ {
+ if(theNavigator->needsContinuousUpdate()||theNavigator->redrawFlag())
+ {
+ theNavigator->update();
+ }
+ }
+
+ break;
+ }
+ case GUIEventAdapter::PUSH:
+ {
+ switch(ea.getButton())
+ {
+ case GUIEventAdapter::LEFT_MOUSE_BUTTON:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ iac->executeBoundAction((modKeyString + "left_mousedown").c_str());
+ break;
+ }
+ case GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ iac->executeBoundAction((modKeyString + "middle_mousedown").c_str());
+ break;
+ }
+ case GUIEventAdapter::RIGHT_MOUSE_BUTTON:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ iac->executeBoundAction((modKeyString + "right_mousedown").c_str());
+ break;
+ }
+ }
+ break;
+ }
+ case GUIEventAdapter::DOUBLECLICK:
+ {
+ switch(ea.getButton())
+ {
+ case GUIEventAdapter::LEFT_MOUSE_BUTTON:
+ {
+ break;
+ }
+ case GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
+ {
+ break;
+ }
+ case GUIEventAdapter::RIGHT_MOUSE_BUTTON:
+ {
+ break;
+ }
+ }
+ }
+ case GUIEventAdapter::RELEASE:
+ {
+ switch(ea.getButton())
+ {
+ case GUIEventAdapter::LEFT_MOUSE_BUTTON:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ iac->executeBoundAction((modKeyString + "left_mouseup").c_str());
+ break;
+ }
+ case GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ iac->executeBoundAction((modKeyString + "middle_mouseup").c_str());
+ break;
+ }
+ case GUIEventAdapter::RIGHT_MOUSE_BUTTON:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ iac->executeBoundAction((modKeyString + "right_mouseup").c_str());
+ break;
+ }
+ }
+ break;
+ }
+ case GUIEventAdapter::SCROLL:
+ {
+ switch(ea.getScrollingMotion())
+ {
+ case GUIEventAdapter::SCROLL_RIGHT:
+ {
+ ossimString s ="scroll_right";
+ s = modKeyString + s;
+ iac->executeBoundAction(s);
+ break;
+ }
+
+ case GUIEventAdapter::SCROLL_LEFT:
+ {
+ ossimString s ="scroll_left";
+ s = modKeyString + s;
+ iac->executeBoundAction(s);
+ break;
+ }
+ case GUIEventAdapter::SCROLL_UP:
+ {
+ break;
+ }
+ case GUIEventAdapter::SCROLL_DOWN:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+// case GUIEventAdapter::MOVE:
+ case GUIEventAdapter::DRAG:
+ {
+ iac->updateInteractionValuators("x_mouse", ea.getXnormalized());
+ iac->updateInteractionValuators("y_mouse", ea.getYnormalized());
+ break;
+ }
+ case GUIEventAdapter::KEYDOWN:
+ {
+ ossimString s;
+ switch(ea.getKey())
+ {
+ case osgGA::GUIEventAdapter::KEY_Up:
+ {
+ us.requestRedraw();
+ s += "up";
+ break;
+ }
+ case osgGA::GUIEventAdapter::KEY_Down:
+ {
+ us.requestRedraw();
+
+ s += "down";
+ break;
+ }
+ case osgGA::GUIEventAdapter::KEY_Left:
+ {
+ us.requestRedraw();
+ s += "left";
+ break;
+ }
+ case osgGA::GUIEventAdapter::KEY_Right:
+ {
+ us.requestRedraw();
+ s += "right";
+ break;
+ }
+ case osgGA::GUIEventAdapter::KEY_Return:
+ {
+ s += "return";
+ us.requestRedraw();
+ break;
+ }
+ case ' ':
+ {
+ s+= "space";
+ us.requestRedraw();
+ break;
+ }
+ default:
+ {
+ s += (char)ea.getKey();
+ break;
+ }
+ }
+ if(s != "")
+ {
+ s+="_key";
+ modKeyString = modKeyString.substitute("shift_",
+ "");
+ s = modKeyString + s;
+ iac->executeBoundAction(s);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ if(theNavigator->needsContinuousUpdate())
+ {
+ us.requestRedraw();
+ }
+ if(theNavigator->redrawFlag())
+ {
+ us.requestRedraw();
+ theNavigator->setRedrawFlag(false);
+ }
+ if(!theUseFrameEventForUpdateFlag)
+ {
+ if(theNavigator->needsContinuousUpdate()||theNavigator->redrawFlag())
+ {
+ theNavigator->update();
+ }
+ }
+
+ return false;
+}
+
+void ossimPlanetManipulator::getUsage(osg::ApplicationUsage& /*usage*/) const
+{
+}
+
+void ossimPlanetManipulator::setLockToNode(osg::Node* node)
+{
+ theLockToNode = node;
+}
+
+void ossimPlanetManipulator::updateViewMatrixNodes()
+{
+ if(theViewMatrixBuilder->fromNode()!=theLockFromNode.get())
+ {
+ ossimPlanetViewMatrixBuilder::Visitor nv;
+ if(theLockFromNode.valid())
+ {
+ theLockFromNode->accept(nv);
+ if(nv.theLsrSpaceTransform.valid())
+ {
+ nv.theLsrSpaceTransform->removeCallback(theFromNodeCallback.get());
+ }
+ }
+ nv.reset();
+ // setup from node
+ //
+ theLockFromNode = theViewMatrixBuilder->fromNode();
+ if(theLockFromNode.valid())
+ {
+ theLockFromNode->accept(nv);
+ if(nv.theLsrSpaceTransform.valid())
+ {
+ nv.theLsrSpaceTransform->addCallback(theFromNodeCallback.get());
+ }
+ else
+ {
+ theLockFromNode = 0;
+ }
+ }
+ }
+ if(theViewMatrixBuilder->toNode()!=theLockToNode.get())
+ {
+ ossimPlanetViewMatrixBuilder::Visitor nv;
+ if(theLockToNode.valid())
+ {
+ theLockToNode->accept(nv);
+ if(nv.theLsrSpaceTransform.valid())
+ {
+ nv.theLsrSpaceTransform->removeCallback(theToNodeCallback.get());
+ }
+ }
+ nv.reset();
+ // setup from node
+ //
+ theLockToNode = theViewMatrixBuilder->toNode();
+ if(theLockToNode.valid())
+ {
+ theLockToNode->accept(nv);
+ if(nv.theLsrSpaceTransform.valid())
+ {
+ nv.theLsrSpaceTransform->addCallback(theToNodeCallback.get());
+ }
+ else
+ {
+ theLockToNode = 0;
+ }
+ }
+ }
+}
+
+bool ossimPlanetManipulator::calculateLineOfSiteLatLonHeight(osg::Vec3d& latLonHeight)
+{
+ bool hitFound = false;
+ if(theNode.valid()&&theNavigator->landModel())
+ {
+ osg::Matrixd m = getMatrix();
+
+ osg::BoundingSphere bs = theNode->getBound();
+ osgUtil::IntersectVisitor iv;
+
+ osg::Vec3d center;
+ osg::Vec3d look(- m(2,0),-m(2,1),-m(2,2));
+ osg::Vec3d eye(m(3,0),m(3,1),m(3,2));
+
+ center = eye + look*100.0;
+
+ osg::ref_ptr<osg::LineSegment> segLookVector = new osg::LineSegment;
+ segLookVector->set(eye, center);
+ iv.addLineSegment(segLookVector.get());
+
+ theNode->accept(iv);
+ if (iv.hits())
+ {
+ osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segLookVector.get());
+ if (!hitList.empty())
+ {
+ osg::Vec3d intersection = hitList.front().getWorldIntersectPoint();
+
+ theNavigator->landModel()->inverse(intersection, latLonHeight);
+ hitFound = true;
+ theFusionDistance = (eye-intersection).length();
+ }
+ }
+
+ }
+ return hitFound;
+}
+
+void ossimPlanetManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ osg::Matrixd m;
+ m.invert(matrix);
+ if (!theNavigator->landModel().valid())
+ ossimPlanetDestinationCommandAction(":navigator reset").execute();
+ else
+ theNavigator->setViewParameters(m);
+}
+
+osg::Matrixd ossimPlanetManipulator::getMatrix() const
+{
+ if(theViewMatrixBuilder->isValid())
+ {
+ theNavigator->setViewParameters(theViewMatrixBuilder->viewMatrix());
+//std::cout << "theViewMatrixBuilder->viewMatrix()" << std::endl;
+ return theViewMatrixBuilder->viewMatrix();
+ }
+ else
+ {
+//std::cout << "theNavigator->viewMatrix()" << std::endl;
+ return theNavigator->viewMatrix();
+ }
+}
+
+osg::Matrixd ossimPlanetManipulator::getInverseMatrix() const
+{
+ if(theViewMatrixBuilder->isValid())
+ {
+ return theViewMatrixBuilder->inverseViewMatrix();
+ }
+ else
+ {
+ return osg::Matrix::inverse(theNavigator->viewMatrix());
+ }
+}
+
+osg::Vec3d ossimPlanetManipulator::eyePosition()const
+{
+ if(theViewMatrixBuilder->isValid())
+ {
+ osg::Vec3d(0,0,0)*theViewMatrixBuilder->viewMatrix();
+ }
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ return osg::Vec3d(0,0,0)*theNavigator->viewMatrix();
+}
+
+void ossimPlanetManipulator::updateNavigator()
+{
+ theNavigator->update();
+}
+
+void ossimPlanetManipulator::setLatitude(double value)
+{
+ theNavigator->setLatLonHeight(value, theNavigator->lon(), theNavigator->elev());
+}
+
+void ossimPlanetManipulator::setLongitude(double value)
+{
+ theNavigator->setLatLonHeight(theNavigator->lat(), value, theNavigator->elev());
+}
+
+void ossimPlanetManipulator::setAltitude(double value)
+{
+ theNavigator->setLatLonHeight(theNavigator->lat(), theNavigator->lon(), value);
+}
+
+void ossimPlanetManipulator::setLatitudeLongitudeAltitude(double lat, double lon, double alt)
+{
+ theNavigator->setLatLonHeight(lat, lon, alt);
+}
+
+void ossimPlanetManipulator::setPosition(const osg::Vec3d& pos)
+{
+ theNavigator->setLatLonHeight(pos[0], pos[1], pos[2]);
+}
+
+void ossimPlanetManipulator::setHeading(double value)
+{
+ theNavigator->setHpr(value, theNavigator->orientation()[1], theNavigator->orientation()[2]);
+}
+
+void ossimPlanetManipulator::setPitch(double value)
+{
+ theNavigator->setHpr(theNavigator->orientation()[0], value, theNavigator->orientation()[2]);
+}
+
+void ossimPlanetManipulator::setRoll(double value)
+{
+ theNavigator->setHpr(theNavigator->orientation()[0], theNavigator->orientation()[1], value);
+}
+
+void ossimPlanetManipulator::setHeadingPitchRoll(double h, double p, double r)
+{
+ theNavigator->setHpr(h, p, r);
+}
+
+void ossimPlanetManipulator::setOrientation(const osg::Vec3d& orien)
+{
+ theNavigator->setHpr(orien[0], orien[1], orien[2]);
+}
+
+void ossimPlanetManipulator::setPositionAndOrientation(double lat, double lon, double alt,
+ double h, double p, double r)
+{
+ theNavigator->setLatLonHeight(lat, lon, alt);
+ theNavigator->setHpr(h, p, r);
+}
+
+void ossimPlanetManipulator::setPositionAndOrientation(const osg::Vec3d& pos,
+ const osg::Vec3d& orien)
+{
+ theNavigator->setLatLonHeight(pos[0], pos[1], pos[2]);
+ theNavigator->setHpr(orien[0], orien[1], orien[2]);
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetNavigator.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetNavigator.cpp
new file mode 100644
index 0000000..2e71615
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetNavigator.cpp
@@ -0,0 +1,1460 @@
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <math.h>
+#include <osg/Quat>
+#include <osg/Timer>
+#include <osg/io_utils>
+#include <ossim/base/ossimString.h>
+#include <ossimPlanet/ossimPlanetNavigator.h>
+#include <ossimPlanet/ossimPlanetPrimaryBody.h>
+#include <ossimPlanet/ossimPlanetInteractionController.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetActionRouter.h>
+
+static inline void adjustHeight(osg::Vec3d& input,
+ ossimPlanetAltitudeMode mode,
+ ossimPlanetGeoRefModel* modelTransform)
+{
+ switch(mode)
+ {
+ case ossimPlanetAltitudeMode_CLAMP_TO_GROUND:
+ {
+ input[2] = modelTransform->getHeightAboveEllipsoid(input[0], input[1]);
+ break;
+ }
+ case ossimPlanetAltitudeMode_RELATIVE_TO_GROUND:
+ {
+ input[2]+=modelTransform->getHeightAboveEllipsoid(input[0], input[1]);
+ break;
+ }
+ case ossimPlanetAltitudeMode_ABSOLUTE:
+ {
+ input[2] += modelTransform->getGeoidOffset(input[0], input[2]);
+ break;
+ }
+ default:
+ {
+ input[2] = modelTransform->getHeightAboveEllipsoid(input[0], input[1]);
+ break;
+ }
+ }
+}
+
+ossimPlanetNavigator::ossimPlanetNavigator(osg::ref_ptr<ossimPlanetPrimaryBody> p) :
+ pitchOffset_(0.0),
+ lat_(0.0),
+ lon_(-90.0),
+ zoomMin_(-4.2), // earth about fills the screen here
+ fov_(50),
+ primary_(p),
+ rotating_(false),
+ zooming_(false),
+ zoominglos_(false),
+ looking_(false),
+ endLooking_(false),
+ gotoing_(false),
+ gotoingelev_(false),
+ gotoset_(false),
+ flying_(false),
+ losLookingFlag_(false),
+ losXYZValidFlag_(false),
+ updateRatePerSecond_(120),
+ lastUpdateTime_(osg::Timer::instance()->tick()),
+ gotoLookDuration_(4.0),
+ xFly_(0.0),
+ yFly_(0.0),
+ theAnimationMode(ossimPlanetNavigator::NAV_ANIMATION_NONE),
+ theAnimationPath(new osg::AnimationPath)
+{
+ thePlanet = 0;
+
+ // earth is above us, eliminates gimbal lock in looking.
+ eyexyz_.set(0.0, 0.0, zoomMin_); // all the way out
+ eyehpr_.set(0.0, pitchOffset_, 0.0); // looking down (up in pf coords) at earth
+ theUseTimedUpdateFlag = false;
+ setRedrawFlag(true);
+}
+
+ossimPlanetNavigator::~ossimPlanetNavigator()
+{
+}
+
+osg::Matrixd ossimPlanetNavigator::orientationLsrMatrix(double lat, double lon, double hgt, double h, double p, double r) const
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ if(!model.valid()) return osg::Matrixd();
+ osg::Matrixd output;
+ model->lsrMatrix(osg::Vec3d(lat, lon, hgt),
+ output);
+ output(3,0) = 0.0;
+ output(3,1) = 0.0;
+ output(3,2) = 0.0;
+
+
+ NEWMAT::Matrix orien = ossimMatrix4x4::createRotationZMatrix(h, OSSIM_RIGHT_HANDED)*
+ ossimMatrix4x4::createRotationXMatrix(p-pitchOffset(), OSSIM_LEFT_HANDED)*
+ ossimMatrix4x4::createRotationYMatrix(r, OSSIM_LEFT_HANDED);
+ osg::Matrixd tempM(orien[0][0], orien[1][0], orien[2][0], 0.0,
+ orien[0][1], orien[1][1], orien[2][1], 0.0,
+ orien[0][2], orien[1][2], orien[2][2], 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+
+ return tempM*output;
+}
+
+void ossimPlanetNavigator::setLatLonHeight(double lat, double lon, double height)
+{
+ lat_ = lat;
+ lon_ = lon;
+ eyexyz_.z() = ossim::clamp(-(1.0 + (height/primary_->radius(lat_))), zoomMin_, zoomMax_);
+}
+void ossimPlanetNavigator::setHpr(double h, double p, double r)
+{
+ eyehpr_.set(h,p,r);
+}
+
+double ossimPlanetNavigator::metersToCenter() const
+{
+ return -eyexyz_.z()*primary_->radius(lat());
+}
+
+void ossimPlanetNavigator::update()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ if(!model.valid()) return;
+ // cache initial values, we need them at the end to update idol
+ //double oldLat(lat()), oldLon(lon()), oldElev(elev());
+ //bool oldGotoing(gotoing_);
+
+ // get current logical valuators
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ float inputLat = iac->interactionValuatorValue("LAT") - baseInputLat_;
+ float inputLon = iac->interactionValuatorValue("LON") - baseInputLon_;
+ float inputZoom = iac->interactionValuatorValue("ZOOM") - baseInputZoom_;
+ float inputYaw = iac->interactionValuatorValue("YAW") - baseInputYaw_;
+ float inputPitch = iac->interactionValuatorValue("PITCH") - baseInputPitch_;
+ bool canUpdateNonTimedUpdates = true;
+ if(theUseTimedUpdateFlag)
+ {
+ double delta = osg::Timer::instance()->delta_s(lastUpdateTime_, osg::Timer::instance()->tick());
+ if(delta < 0.0)
+ {
+ // bad time tick so reset
+ lastUpdateTime_ = osg::Timer::instance()->tick();
+ return;
+ }
+ canUpdateNonTimedUpdates = (delta > (1.0/updateRatePerSecond_));
+ }
+#if 1
+ if (theAnimationMode == NAV_ANIMATION_PLAYBACK)
+ {
+
+ if (!rotating_ && !zooming_ && !losLookingFlag_ && !zoominglos_ && !flying_)
+ {
+ double t = osg::Timer::instance()->delta_s( theAnimationStartTime, osg::Timer::instance()->tick());
+ if (t >= 0.0)
+ {
+ osg::Matrixd m;
+ if (theAnimationPath->getMatrix(t, m))
+ {
+ setViewParameters(m);
+ return;
+ }
+ else
+ {
+ theAnimationMode = NAV_ANIMATION_NONE;
+ }
+ }
+ else
+ {
+ theAnimationStartTime = osg::Timer::instance()->tick();// need to reset the timer since went negative
+ }
+ }
+ else
+ {
+ theAnimationMode = NAV_ANIMATION_NONE;
+ }
+ }
+#endif
+
+ if (canUpdateNonTimedUpdates)
+ {
+ lastUpdateTime_ = osg::Timer::instance()->tick();
+ }
+ if (zoominglos_ && losXYZValidFlag_ && model.valid())
+ {
+
+ osg::Matrixd eyeLsrMatrix = viewMatrix();
+ osg::Vec3d eye(eyeLsrMatrix(3,0), eyeLsrMatrix(3,1), eyeLsrMatrix(3,2));
+ osg::Vec3d posXYZ;
+ osg::Vec3d posLlh;
+ osg::Vec3d tempHpr;
+ osg::Vec3d deltaV = eye-losXYZ_; //losXYZ-eye;
+ double distanceCurrent = deltaV.length();
+ double minDistance = 64.0/model->getNormalizationScale();
+ double distance = distanceCurrent + distanceCurrent*0.1*inputZoom;
+
+ if (distance < minDistance)
+ {
+ distance = minDistance;
+ }
+ deltaV.normalize();
+
+ posXYZ = losXYZ_ + deltaV*distance;
+
+ model->inverse(posXYZ, posLlh);
+
+ setLatLonHeight(posLlh[0], posLlh[1], posLlh[2]);//*model->getNormalizationScale());
+ osg::Matrixd localLsr;
+ model->lsrMatrix(posLlh, localLsr);
+
+ mkUtils::matrixToHpr(tempHpr, localLsr, eyeLsrMatrix);
+ eyehpr_ = tempHpr;
+ eyehpr_[2] = 0.0;
+ eyehpr_[0] = ossim::clamp(eyehpr_[0] , -180.0, 180.0);
+ eyehpr_[1] = ossim::clamp(eyehpr_[1] , 0.0, 180.0);
+ }
+ if (losLookingFlag_ && losXYZValidFlag_ && model.valid())
+ {
+ if (canUpdateNonTimedUpdates)
+ {
+
+ osg::Matrixd eyeLsrMatrix = viewMatrix();
+ osg::Vec3d eye(eyeLsrMatrix(3,0), eyeLsrMatrix(3,1), eyeLsrMatrix(3,2));
+ double distance = (losXYZ_ - eye).length();
+ eyeLsrMatrix(3,0) = 0.0;
+ eyeLsrMatrix(3,1) = 0.0;
+ eyeLsrMatrix(3,2) = 0.0;
+
+ double rotationZAmount = inputYaw*(10*M_PI/180.0);
+ double rotationPitchAmount = inputPitch*(10*M_PI/180.0);
+ // osg::Vec3d xn = osg::Vec3d(1.0, 0.0, 0.0);
+ osg::Vec3d zn = losXYZ_;
+ zn.normalize();
+ osg::Matrixd r = osg::Matrix::rotate(rotationZAmount, zn);
+ eyeLsrMatrix = eyeLsrMatrix*r;
+
+ eyeLsrMatrix = eyeLsrMatrix*osg::Matrix::rotate(rotationPitchAmount, osg::Vec3d(eyeLsrMatrix(0,0),
+ eyeLsrMatrix(0,1),
+ eyeLsrMatrix(0,2)));
+ osg::Vec3d newPoint = losXYZ_ + osg::Vec3d(eyeLsrMatrix(2, 0), eyeLsrMatrix(2, 1), eyeLsrMatrix(2, 2))*distance;
+ osg::Vec3d eyeLlh;
+ model->inverse(newPoint, eyeLlh);
+ setLatLonHeight(eyeLlh[0],
+ eyeLlh[1],
+ eyeLlh[2]);//*model->getNormalizationScale());
+
+ osg::Matrixd tempView = viewMatrix();
+ osg::Matrixd localLsr;
+ model->lsrMatrix(eyeLlh, localLsr);
+ osg::Vec3d tempHpr;
+ mkUtils::matrixToHpr(tempHpr, localLsr, eyeLsrMatrix);
+
+ eyehpr_[0] = ossim::clamp(tempHpr[0] , -180.0, 180.0);
+ eyehpr_[1] = ossim::clamp(tempHpr[1] , 0.0, 90.0);
+ eyehpr_[2] = 0.0;
+ // eyehpr_[2] = mkUtils::clamp(eyehpr_[2] , -180.0, 180.0);
+ }
+ }
+ if (flying_)
+ {
+ if (ossim::almostEqual(xFly_, 0.0) && ossim::almostEqual(yFly_, 0.0))
+ {
+ flying_ = false;
+ }
+ else if (canUpdateNonTimedUpdates)
+ {
+ float x = osg::DegreesToRadians(eyehpr_[0]);
+ float s = sin(x);
+ float c = cos(x);
+
+ updateLatLon(xFly_*c + yFly_*s, -xFly_*s + yFly_*c);
+ // updateLatLon(-xFly_*c + yFly_*s, xFly_*s - yFly_*c);
+ }
+ }
+ if (rotating_ && canUpdateNonTimedUpdates)
+ {
+ float x = osg::DegreesToRadians((eyehpr_[0]));// - 90.0));
+ float s = sin(x);
+ float c = cos(x);
+ updateLatLon(inputLon*c + inputLat*s, -inputLon*s + inputLat*c);
+ // updateLatLon(xMouse*c - yMouse*s, xMouse*s + yMouse*c);
+ // updateLatLon(xMouse, yMouse);
+ gotoing_ = false;
+ gotoset_ = false;
+ gotoingelev_ = false;
+ }
+
+ updateZoomParameters();
+
+ if (zooming_ && canUpdateNonTimedUpdates) {
+ double magic = 0.1;
+ eyexyz_.z() = ossim::clamp(eyexyz_.z() + zoomScaleInput(inputZoom)*magic, zoomMin_, zoomMax_);
+ // manual zoom neutralizes the zoom of any gotoing that we might be doing right now
+ targetStartLookZ_ = eyexyz_.z();
+ targetMidpointLookZ_ = eyexyz_.z();
+ targetLookZ_ = eyexyz_.z();
+ }
+ if (looking_ && canUpdateNonTimedUpdates)
+ {
+ double magic = 5.0;
+ eyehpr_[0] = ossim::wrap(eyehpr_[0] - inputYaw*fabsf(inputYaw)*magic, -180.0, 180.0);
+ eyehpr_[1] = ossim::clamp(eyehpr_[1] + inputPitch*fabsf(inputPitch)*magic, 0.0, 180.0);
+ }
+
+ if (gotoing_)
+ {
+ gotoingelev_ = false;
+ double delta = (osg::Timer::instance()->delta_s(gotoStartTime_, osg::Timer::instance()->tick())) / gotoLookDuration_;
+ if((delta < 1.0)&&(delta >= 0.0))
+ {
+ lon_ = ossim::lerp(delta, targetStartLon_, targetLon_);
+ lat_ = ossim::lerp(delta, targetStartLat_, targetLat_);
+ eyexyz_.z() = mkUtils::quaderp(delta, targetStartLookZ_, targetMidpointLookZ_, targetLookZ_);
+ eyehpr_[0] = ossim::lerp(delta, targetStartLookH_, targetLookH_);
+ // eyehpr_[1] = mkUtils::lerp(delta, targetStartLookP_, targetLookP_);
+ eyehpr_[1] = mkUtils::quaderp(delta, targetStartLookP_, 0.0, targetLookP_);
+ eyehpr_[2] = ossim::lerp(delta, targetStartLookR_, targetLookR_);
+ }
+ else
+ {
+ lon_ = targetLon_;
+ lat_ = targetLat_;
+ eyexyz_.z() = targetLookZ_;
+ eyehpr_[0] = targetLookH_;
+ eyehpr_[1] = targetLookP_;
+ eyehpr_[2] = targetLookR_;
+ gotoing_ = false;
+ }
+ }
+#if 1
+ if (theAnimationMode == NAV_ANIMATION_RECORDING)
+ {
+ osg::Matrixd m = viewMatrix();
+ osg::Vec3d eye(m(3,0), m(3,1), m(3,2));
+ osg::Vec3d orient = orientation();
+ if (theAnimationPath->empty())
+ {
+ osg::Quat quat = m.getRotate();
+ osg::AnimationPath::ControlPoint cp(eye, quat);
+
+ theLastAnimationParameter.quat = quat;
+ theLastAnimationParameter.orientation = orient;
+ theLastAnimationParameter.eye = eye;
+ theAnimationPath->insert(0.0, cp);
+
+ }
+ else if (!ossim::almostEqual(eye[0], theLastAnimationParameter.eye[0]) ||
+ !ossim::almostEqual(eye[1], theLastAnimationParameter.eye[1]) ||
+ !ossim::almostEqual(eye[2], theLastAnimationParameter.eye[2]) ||
+ !ossim::almostEqual(orient[0], theLastAnimationParameter.orientation[0]) ||
+ !ossim::almostEqual(orient[1], theLastAnimationParameter.orientation[1]) ||
+ !ossim::almostEqual(orient[2], theLastAnimationParameter.orientation[2]))
+ {
+ theAnimationPath->insert(osg::Timer::instance()->delta_s(theAnimationStartTime, osg::Timer::instance()->tick()),
+ osg::AnimationPath::ControlPoint(theLastAnimationParameter.eye,
+ theLastAnimationParameter.quat));
+
+ osg::Quat quat = m.getRotate();
+ osg::AnimationPath::ControlPoint cp(eye, quat);
+
+ theLastAnimationParameter.quat = quat;
+ theLastAnimationParameter.orientation = orient;
+ theLastAnimationParameter.eye = eye;
+ theAnimationPath->insert(osg::Timer::instance()->delta_s(theAnimationStartTime, osg::Timer::instance()->tick()), cp);
+ }
+ }
+#endif
+#if 0
+ // if our lat/lon/elev has changed, send it to the IDOL Browser Agent.
+ // note that "idolfederation" is a totally ad hoc name.
+ // XXX there should be a flag that determines if we should output this or not?
+ if (!oldGotoing && !gotoing_ && (oldLat != lat() || oldLon != lon() || oldElev != elev())) {
+ std::ostringstream out;
+ out.precision(16);
+ out << ":idolbridge gotolatlonelev " << lat() << " " << lon() << " " << elev();
+ ossimPlanetAction(out.str()).allExecute();
+ }
+#endif
+}
+
+osg::Vec3d ossimPlanetNavigator::centerOfInterest() const
+{
+ if (!gotoing_)
+ return osg::Vec3d(lat_, lon_, elev());
+ else
+ return osg::Vec3d(targetLat_, targetLon_, -targetLookZ_*primary_->equatorialRadius());
+}
+
+void ossimPlanetNavigator::updateZoomParameters()
+{
+ double r = primary_->radius(lat_)/primary_->equatorialRadius();
+ zoomMin_ = -4.2; // earth about fills the screen here
+ zoomMax_ = 0.0; // we will need to let current intersection of Line of site handle this if we could
+// zoomMax_ = -1.000001*r; // close enough
+ zoomScaleBaseline_ = r;
+
+ eyexyz_.z() = ossim::clamp(eyexyz_.z(), zoomMin_, zoomMax_);
+}
+
+void ossimPlanetNavigator::setViewParameters(const osg::Matrixd& m)
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model=landModel();
+ if (model.valid())
+ {
+ osg::Matrixd tempM;
+ osg::Vec3d translation;
+ osg::Vec3d scale;
+ osg::Quat rotation;
+ osg::Quat s;
+ osg::Vec3d latLonHeight;
+ osg::Vec3d hpr;
+ // deomcpose some of the parts we need
+ //
+ m.decompose(translation, rotation, scale, s);
+ model->inverse(translation, latLonHeight);
+ model->lsrMatrix(latLonHeight, tempM);
+ mkUtils::matrixToHpr(eyehpr_, tempM, m);
+ //std::cout << "HPR mkutils = " << eyehpr_ << std::endl;
+ setLatLonHeight(latLonHeight[0],
+ latLonHeight[1],
+ latLonHeight[2]);
+ }
+}
+
+void ossimPlanetNavigator::extractCameraParameters(ossimRefPtr<ossimXmlNode> node,
+ double& lat,
+ double& lon,
+ double& alt,
+ double& h,
+ double& p,
+ double& r)const
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ ossimString vref = node->getAttributeValue("vref");
+ ossimString value;
+ lat = lat_;
+ lon = lon_;
+ alt = elev();
+ h = eyehpr_[0];
+ p = eyehpr_[1];
+ r = eyehpr_[2];
+
+ if(node->getChildTextValue(value, "longitude"))
+ {
+ lon = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "latitude"))
+ {
+ lat = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "altitude"))
+ {
+ alt = value.toDouble();
+ if(node->getChildTextValue(value, "altitudeMode"))
+ {
+ if(value.contains("relative"))
+ {
+ alt += model->getHeightAboveEllipsoid(lat, lon);
+ }
+ else if(value.contains("clamp"))
+ {
+ alt = model->getHeightAboveEllipsoid(lat, lon);
+ }
+ else if(value.contains("absolute"))
+ {
+ if(vref!="wgs84")
+ {
+ alt += model->getGeoidOffset(lat, lon);
+ }
+ }
+ }
+ }
+ if(node->getChildTextValue(value, "heading"))
+ {
+ h = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "pitch"))
+ {
+ p = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "roll"))
+ {
+ r = value.toDouble();
+ }
+}
+
+void ossimPlanetNavigator::extractLookAtParameters(ossimRefPtr<ossimXmlNode> node,
+ ossimPlanetLookAt& look)const
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ double lat=0.0;
+ double lon=0.0;
+ double altitude=0.0;
+ double h=0.0;
+ double p=0.0;
+ double r=0.0;
+ double range=0.0;
+ ossimString value;
+ ossimString vref = node->getAttributeValue("vref");
+ // solve current view as a lookat
+ solveLookAt(lat, lon, altitude, h, p, r, range);
+
+ if(node->getChildTextValue(value, "longitude"))
+ {
+ lon = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "latitude"))
+ {
+ lat = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "altitude"))
+ {
+ altitude = value.toDouble();
+ if(node->getChildTextValue(value, "altitudeMode"))
+ {
+ if(value.contains("relative"))
+ {
+ altitude += model->getHeightAboveEllipsoid(lat, lon);
+ }
+ else if(value.contains("clamp"))
+ {
+ altitude = model->getHeightAboveEllipsoid(lat, lon);
+ }
+ else if(value.contains("absolute"))
+ {
+ if(vref!="wgs84")
+ {
+ altitude += model->getGeoidOffset(lat, lon);
+ }
+ }
+ }
+ }
+ if(node->getChildTextValue(value, "heading"))
+ {
+ h = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "pitch"))
+ {
+ p = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "roll"))
+ {
+ r = value.toDouble();
+ }
+ if(node->getChildTextValue(value, "range"))
+ {
+ range = value.toDouble();
+ }
+ look.setAll(lat, lon, altitude,
+ h, p, r,
+ range, ossimPlanetAltitudeMode_ABSOLUTE);
+}
+
+void ossimPlanetNavigator::xmlExecute(const ossimPlanetXmlAction& a)
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ ossimString command = a.command();
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ if(command == "Set")
+ {
+ ossim_uint32 idx = 0;
+ for(;idx < children.size();++idx)
+ {
+ if(children[idx]->getTag() == "Camera")
+ {
+ double altitude = 0.0;
+
+ // get the altitude vertical frame of reference: msl or wgs84
+ extractCameraParameters(children[idx],
+ lat_,
+ lon_,
+ altitude,
+ eyehpr_[0],
+ eyehpr_[1],
+ eyehpr_[2]);
+
+ targetLon_ = lon_;
+ targetLat_ = lat_;
+ eyexyz_.z() = ossim::clamp(-altitude/primary_->radius(targetLat_) - 1.0, zoomMin_, zoomMax_);
+ targetLookZ_ = eyexyz_.z();
+ targetStartLookZ_ = eyexyz_.z();
+ targetLookH_ = eyehpr_[0];
+ targetLookP_ = eyehpr_[1];
+ targetLookR_ = eyehpr_[2];
+ setRedrawFlag(true);
+ }
+ else if(children[idx]->getTag() == "LookAt")
+ {
+ osg::Vec3d llh;
+ osg::Vec3d hpr;
+ ossimPlanetLookAt look;
+ extractLookAtParameters(children[idx],
+ look);
+ solveEyeGivenLocalSpaceAndRange(llh, hpr, osg::Vec3d(look.lat(), look.lon(), look.altitude()), osg::Vec3d(look.heading(),look.pitch(),look.roll()), look.range());
+ lon_ = llh[1];
+ targetLon_ = llh[1];
+ lat_ = llh[0];
+ targetLat_ = llh[0];
+ eyexyz_.z() = ossim::clamp(-llh[2]/primary_->radius(targetLat_) - 1.0, zoomMin_, zoomMax_);
+ targetLookZ_ = eyexyz_.z();
+ targetStartLookZ_ = eyexyz_.z();
+ eyehpr_[0] = hpr[0];
+ targetLookH_ = eyehpr_[0];
+ eyehpr_[1] = hpr[1];
+ targetLookP_ = eyehpr_[1];
+ eyehpr_[2] = hpr[2];
+ targetLookR_ = eyehpr_[2];
+ setRedrawFlag(true);
+ }
+ }
+ }
+ else if(command == "Get")
+ {
+ }
+ else if(command == "FlyTo")
+ {
+ ossim_uint32 idx = 0;
+ for(;idx < children.size();++idx)
+ {
+ if(children[idx]->getTag() == "Camera")
+ {
+ double lat=0.0,lon=0.0;
+ double altitude = 0.0;
+ double h=0.0,p=0.0,r=0.0;
+ // get the altitude vertical frame of reference: msl or wgs84
+ extractCameraParameters(children[idx],
+ lat,
+ lon,
+ altitude,
+ h,
+ p,
+ r);
+ gotoLatLonElevHpr("", lat, lon, altitude,
+ h,
+ p,
+ r);
+
+ setRedrawFlag(true);
+ }
+ else if(children[idx]->getTag() == "LookAt")
+ {
+ ossimPlanetLookAt look;
+ extractLookAtParameters(children[idx],
+ look);
+ gotoLookAt(look);
+ }
+ }
+ }
+}
+
+void ossimPlanetNavigator::destinationCommandExecute(const ossimPlanetDestinationCommandAction& a)
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ if(!model.valid()) return;
+ ossimString command = a.command();
+ if ("rotatestart" == command)
+ {
+ setRedrawFlag(true);
+ rotating_ = true;
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ if(!losLookingFlag_) // only upate if not been initialize by someone else
+ {
+ baseInputLon_ = iac->interactionValuatorValue("LON");
+ baseInputLat_ = iac->interactionValuatorValue("LAT");
+ }
+ }
+ else if ("recordanimation" == command)
+ {
+ setRedrawFlag(true);
+ startRecording();
+ }
+ else if ("playanimation" == command)
+ {
+ setRedrawFlag(true);
+ playRecording();
+ }
+ else if ("stopanimation" == command)
+ {
+ setRedrawFlag(true);
+ stopRecording();
+ }
+ else if ("saveanimation" == command)
+ {
+ if (a.argCount() == 1)
+ {
+ std::ofstream outFile(a.arg(1).c_str());
+ std::ostringstream outString;
+ outFile << "<animationPath>";
+ theAnimationPath->write(outString);
+ ossimString tempString = ossimString(outString.str().c_str()).substitute("\n", " ", true);
+ outFile << tempString << "</animationPath>";
+ }
+ else
+ {
+ a.printError("bad argument count");
+ }
+ }
+ else if ("rotatestop" == command)
+ {
+ setRedrawFlag(true);
+ rotating_ = false;
+ }
+ else if ("losrotatestart" == command)
+ {
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ // if(!rotating_)
+ // {
+ // baseInputLon_ = iac->interactionValuatorValue("LON");
+ // baseInputLat_ = iac->interactionValuatorValue("LAT");
+ // }
+ if(!looking_)
+ {
+ baseInputYaw_ = iac->interactionValuatorValue("YAW");
+ baseInputPitch_ = iac->interactionValuatorValue("PITCH");
+ }
+ losLookingFlag_ = true;
+ losXYZValidFlag_ = false;
+ }
+ else if ("losrotatestop" == command)
+ {
+ setRedrawFlag(true);
+ losLookingFlag_ = false;
+ losXYZValidFlag_ = false;
+ }
+ else if ("loszoomstart" == command)
+ {
+ setRedrawFlag(true);
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ if(!zooming_)
+ {
+ baseInputZoom_ = iac->interactionValuatorValue("ZOOM");
+ }
+ losXYZValidFlag_ = false;
+ zoominglos_ = true;
+ }
+ else if ("loszoomstop" == command)
+ {
+ setRedrawFlag(true);
+ zoominglos_ = false;
+ losXYZValidFlag_ = false;
+ }
+ else if ("zoomstart" == command)
+ {
+ setRedrawFlag(true);
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ if(!zoominglos_)
+ {
+ baseInputZoom_ = iac->interactionValuatorValue("ZOOM");
+ }
+ losXYZValidFlag_ = false;
+ zooming_ = true;
+ }
+ else if ("zoomstop" == command)
+ {
+ setRedrawFlag(true);
+ zooming_ = false;
+ }
+ else if ("lookstart" == command)
+ {
+ setRedrawFlag(true);
+ looking_ = true;
+ endLooking_ = false;
+ ossimPlanetInteractionController* iac = ossimPlanetInteractionController::instance();
+ if(!losLookingFlag_)
+ {
+ baseInputYaw_ = iac->interactionValuatorValue("YAW");
+ baseInputPitch_ = iac->interactionValuatorValue("PITCH");
+ }
+ }
+ else if ("los" == command)
+ {
+ if (a.argCount() == 3)
+ {
+ if (a.arg(1) == "nan" || a.arg(2) == "nan" || a.arg(3) == "nan")
+ {
+ losXYZValidFlag_ = false;
+ }
+ }
+ else if (a.argCount() == 0)
+ {
+ losXYZValidFlag_ = false;
+ }
+ else
+ {
+ a.printError("bad argument count");
+ }
+ }
+
+ else if ("lookstop" == command)
+ {
+ setRedrawFlag(true);
+ looking_ = false;
+ endLooking_ = true;
+ endLookingStartTime_ = osg::Timer::instance()->tick();
+ }
+ else if ("flystart" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 2)
+ {
+ if (!flying_)
+ {
+ flying_ = true;
+ xFly_ = mkUtils::asDouble(a.arg(1));
+ yFly_ = mkUtils::asDouble(a.arg(2));
+ }
+ else
+ {
+ xFly_ += mkUtils::asDouble(a.arg(1));
+ yFly_ += mkUtils::asDouble(a.arg(2));
+ }
+ }
+ else
+ {
+ a.printError("bad argument count");
+ }
+ }
+ else if ("gotolookat" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 7)
+ {
+ ossimPlanetLookAt info;
+
+ info.setAll(mkUtils::asDouble(a.arg(1)),// lat
+ mkUtils::asDouble(a.arg(2)),// lon
+ mkUtils::asDouble(a.arg(3)),// altitude
+ mkUtils::asDouble(a.arg(4)),// heading
+ mkUtils::asDouble(a.arg(5)),// pitch
+ mkUtils::asDouble(a.arg(6)),// roll
+ mkUtils::asDouble(a.arg(7)) // range
+ );
+ gotoLookAt(info);
+ }
+ else if (a.argCount() == 8)
+ {
+ ossimPlanetLookAt info;
+
+ info.setAll(mkUtils::asDouble(a.arg(1)),// lat
+ mkUtils::asDouble(a.arg(2)),// lon
+ mkUtils::asDouble(a.arg(3)),// altitude
+ mkUtils::asDouble(a.arg(4)),// heading
+ mkUtils::asDouble(a.arg(5)),// pitch
+ mkUtils::asDouble(a.arg(6)),// roll
+ mkUtils::asDouble(a.arg(7)),// range
+ ossimPlanetLookAt::modeFromString(a.arg(8))); // mode
+ gotoLookAt(info);
+ }
+ else
+ {
+ a.printError("bad argument count, the syntax is gotolookat <lat> <lon> <altitude> <heading> <pitch> <roll> <range> <altitudeMode>");
+ }
+ }
+ else if ("gotolatlon" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 2)
+ gotoLatLonElevHpr("", mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), elev(),
+ eyehpr_[0],
+ eyehpr_[1],
+ eyehpr_[2]);
+ else if (a.argCount() == 3)
+ gotoLatLonElevHpr(a.arg(1), mkUtils::asDouble(a.arg(2)), mkUtils::asDouble(a.arg(3)), elev(),
+ eyehpr_[0],
+ eyehpr_[1],
+ eyehpr_[2]);
+ else
+ a.printError("bad argument count");
+
+ }
+ else if ("zoomtolatlon" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 2)
+ {
+ gotoing_ = false;
+ lat_ = mkUtils::asDouble(a.arg(1));
+ lon_ = mkUtils::asDouble(a.arg(2));
+ targetLat_ = lat_;
+ targetLon_ = lon_;
+ targetLookH_ = eyehpr_[0];
+ targetLookP_ = eyehpr_[1];
+ targetLookR_ = eyehpr_[2];
+ targetLookZ_ = eyexyz_.z();
+ }
+ else if (a.argCount() == 3)
+ {
+ gotoing_ = false;
+ lat_ = mkUtils::asDouble(a.arg(2));
+ lon_ = mkUtils::asDouble(a.arg(3));
+ targetLat_ = lat_;
+ targetLon_ = lon_;
+ targetLookH_ = eyehpr_[0];
+ targetLookP_ = eyehpr_[1];
+ targetLookR_ = eyehpr_[2];
+ targetLookZ_ = eyexyz_.z();
+
+ }
+ else
+ {
+ a.printError("bad argument count");
+ }
+ }
+ else if ("gotolatlonelev" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 3)
+ {
+ gotoLatLonElevHpr("", mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), mkUtils::asDouble(a.arg(3)),
+ eyehpr_[0],
+ eyehpr_[1],
+ eyehpr_[2]);
+ }
+ else if (a.argCount() == 4)
+ gotoLatLonElevHpr(a.arg(1), mkUtils::asDouble(a.arg(2)),
+ mkUtils::asDouble(a.arg(3)), mkUtils::asDouble(a.arg(4)),
+ eyehpr_[0],
+ eyehpr_[1],
+ eyehpr_[2]);
+ else
+ a.printError("bad argument count");
+
+ }
+ else if ("setlatlonelevhpr" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 6)
+ {
+ gotoing_ = false;
+ gotoset_ = false;
+ rotating_ = false;
+ zooming_ = false;
+ zoominglos_ = false;
+ gotoingelev_=false;
+ // gotoing_ = false;
+ // gotoset_ = true;
+
+ lat_ = mkUtils::asDouble(a.arg(1));
+ lon_ = mkUtils::asDouble(a.arg(2));
+ eyexyz_.z() = ossim::clamp(-mkUtils::asDouble(a.arg(3))/primary_->radius(targetLat_) - 1.0, zoomMin_, zoomMax_);
+ eyehpr_[0] =mkUtils::asDouble(a.arg(4));
+ eyehpr_[1] =mkUtils::asDouble(a.arg(5));
+ eyehpr_[2] =mkUtils::asDouble(a.arg(6));
+
+ targetLookZ_ = eyexyz_.z();
+ targetLookH_ = eyehpr_[0];
+ targetLookP_ = eyehpr_[1];
+ targetLookR_ = eyehpr_[2];
+ targetStartLookZ_ = eyexyz_.z();
+ setRedrawFlag(true);
+ //std::cout << "ossimPlanetNavigator: setlatlonelevhpr\n";
+ }
+ else
+ a.printError("bad argument count: should be setlatlonelevhpr <lat> <lon> <elev in meters> <heading> <pitch> <roll>");
+ }
+ // else if ("gotolatlonelevh" == command)
+ // {
+ // if (a.argCount() == 4)
+ // {
+ // gotoLatLonElevHpr("", mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), mkUtils::asDouble(a.arg(3)),
+ // mkUtils::asDouble(a.arg(4)),
+ // eyehpr_[1],
+ // eyehpr_[2]);
+ // }
+ // else if (a.argCount() == 5)
+ // gotoLatLonElevHpr(a.arg(1), mkUtils::asDouble(a.arg(2)),
+ // mkUtils::asDouble(a.arg(3)), mkUtils::asDouble(a.arg(4)),
+ // mkUtils::asDouble(a.arg(5)),
+ // eyehpr_[1],
+ // eyehpr_[2]);
+ // else
+ // a.printError("bad argument count");
+
+ // }
+ else if ("gotolatlonelevhpr" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 6)
+ {
+ gotoLatLonElevHpr("", mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), mkUtils::asDouble(a.arg(3)),
+ mkUtils::asDouble(a.arg(4)),
+ mkUtils::asDouble(a.arg(5)),
+ mkUtils::asDouble(a.arg(6)));
+ }
+ else if (a.argCount() == 7)
+ gotoLatLonElevHpr(a.arg(1), mkUtils::asDouble(a.arg(2)),
+ mkUtils::asDouble(a.arg(3)), mkUtils::asDouble(a.arg(4)),
+ mkUtils::asDouble(a.arg(5)),
+ mkUtils::asDouble(a.arg(6)),
+ mkUtils::asDouble(a.arg(7)));
+ else
+ a.printError("bad argument count");
+
+ }
+ else if ("gotolatlonnadir" == command)
+ {
+ if (a.argCount() == 2)
+ {
+ gotoLatLonElevHpr("", mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), elev(),
+ 0.0, pitchOffset_, 0.0);
+ }
+ else if (a.argCount() == 3)
+ gotoLatLonElevHpr(a.arg(1), mkUtils::asDouble(a.arg(2)),
+ mkUtils::asDouble(a.arg(3)), elev(),
+ 0.0, pitchOffset_, 0.0);
+ else
+ a.printError("bad argument count");
+
+ }
+ else if ("gotolatlonelevnadir" == command)
+ {
+ setRedrawFlag(true);
+ if (a.argCount() == 3)
+ {
+ gotoLatLonElevHpr("", mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), mkUtils::asDouble(a.arg(3)),
+ 0.0, pitchOffset_, 0.0);
+ }
+ else if (a.argCount() == 4)
+ gotoLatLonElevHpr(a.arg(1), mkUtils::asDouble(a.arg(2)),
+ mkUtils::asDouble(a.arg(3)), mkUtils::asDouble(a.arg(4)),
+ 0.0, pitchOffset_, 0.0);
+ else
+ a.printError("bad argument count");
+
+ }
+ else if ("printlatlonelev" == command)
+ {
+ cout << "lat = " << lat_ << " lon = " << lon_ << " elev = " << elev() << 'm' << endl;
+
+ } else if ("printlookcoordinates" == command) {
+ cout << "Look z: " << eyexyz_.z() << " hpr: " << eyehpr_[0] << ' ' << eyehpr_[1] << ' ' << eyehpr_[2] << endl;
+
+ } else if ("gotoxyz" == command) {
+ eyexyz_.set(mkUtils::asDouble(a.arg(1)), mkUtils::asDouble(a.arg(2)), mkUtils::asDouble(a.arg(3)));
+ eyehpr_.set(0.0, pitchOffset_, 0.0);
+
+ } else if ("resetzoomlook" == command) {
+ eyexyz_.set(0.0, 0.0, zoomMin_);
+ eyehpr_.set(0.0, pitchOffset_, 0.0);
+ setRedrawFlag(true);
+
+ } else if ("rotatenorth" == command){
+ setRedrawFlag(true);
+ if(losXYZValidFlag_&&model.valid())
+ {
+ osg::Vec3d llh;
+ osg::Vec3d newLlh;
+ osg::Vec3d xyz;
+ osg::Vec3d hpr;
+ osg::Vec3d newHpr;
+ double range;
+ osg::Vec3d tempHpr;
+
+ // first get the look at orientation
+ // rotated north
+ model->inverse(losXYZ_, llh);
+ solveLookAt(llh[0], llh[1], llh[2],
+ hpr[0], hpr[1], hpr[2],
+ range);
+
+
+ solveEyeGivenLocalSpaceAndRange(newLlh, newHpr, llh, osg::Vec3d(0.0, hpr[1], 0.0), range);
+
+ setLatLonHeight(newLlh[0], newLlh[1], newLlh[2]);
+ eyehpr_ = newHpr;
+ eyehpr_[2] = 0.0;
+ eyehpr_[0] = ossim::clamp(eyehpr_[0] , -180.0, 180.0);
+ eyehpr_[1] = ossim::clamp(eyehpr_[1] , 0.0, 180.0);
+ }
+
+ } else if ("rotatenorthup" == command){
+ setRedrawFlag(true);
+ if(losXYZValidFlag_&&model.valid())
+ {
+ osg::Vec3d llh;
+ osg::Vec3d newLlh;
+ osg::Vec3d xyz;
+ osg::Vec3d hpr;
+ osg::Vec3d newHpr;
+ double range;
+ osg::Vec3d tempHpr;
+
+ // first get the look at orientation
+ // rotated north
+ model->inverse(losXYZ_, llh);
+ solveLookAt(llh[0], llh[1], llh[2],
+ hpr[0], hpr[1], hpr[2],
+ range);
+
+
+ solveEyeGivenLocalSpaceAndRange(newLlh, newHpr, llh, osg::Vec3d(0.0, pitchOffset_, 0.0), range);
+
+ setLatLonHeight(newLlh[0], newLlh[1], newLlh[2]);
+ eyehpr_ = newHpr;
+ eyehpr_[2] = 0.0;
+ eyehpr_[0] = ossim::clamp(eyehpr_[0] , -180.0, 180.0);
+ eyehpr_[1] = ossim::clamp(eyehpr_[1] , 0.0, 180.0);
+ }
+
+ } else if ("setgotolookduration" == command) {
+ if ((a.argCount() == 1) && (mkUtils::asDouble(a.arg(1)) > 0.0)) {
+ gotoLookDuration_ = mkUtils::asDouble(a.arg(1));
+ } else {
+ a.printError("bad argument, need one float > 0");
+ }
+
+ }
+ else if ("reset" == command)
+ {
+ eyexyz_.set(0.0, 0.0, zoomMin_);
+ eyehpr_.set(0.0, pitchOffset_, 0.0);
+ lat_ = 0.0;
+ lon_ = -90.0;
+ rotating_ = false;
+ zooming_ = false;
+ looking_ = false;
+ endLooking_ = false;
+ gotoing_ = false;
+ gotoset_ = false;
+ gotoingelev_ = false;
+ flying_ = false;
+ losLookingFlag_ = false;
+ theAnimationMode = ossimPlanetNavigator::NAV_ANIMATION_NONE;
+ setRedrawFlag(true);
+ }
+ else if ("stop" == command)
+ {
+ setRedrawFlag(true);
+ rotating_ = false;
+ zooming_ = false;
+ looking_ = false;
+ endLooking_ = false;
+ gotoing_ = false;
+ gotoset_ = false;
+ flying_ = false;
+ losLookingFlag_ = false;
+ theAnimationMode = ossimPlanetNavigator::NAV_ANIMATION_NONE;
+ }
+ else
+ {
+ a.printError("bad command");
+ }
+}
+
+
+void ossimPlanetNavigator::execute(const ossimPlanetAction &action)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ const ossimPlanetDestinationCommandAction* a = action.toDestinationCommandAction();
+ const ossimPlanetXmlAction* xml = action.toXmlAction();
+ // for now only support :destination command <args> style actions;
+ if(a)
+ {
+ destinationCommandExecute(*a);
+ }
+ else if(xml)
+ {
+ xmlExecute(*xml);
+ }
+}
+
+// protected
+
+void ossimPlanetNavigator::updateLatLon(float x, float y)
+{
+
+ lon_ = ossim::wrap(lon_ - zoomScaleInput(x), primary_->minLon(), primary_->maxLon());
+ lat_ -= zoomScaleInput(y);
+ if (lat_ > 90.0)
+ {
+ lat_ = ossim::clamp(90.0 - (lat_ - 90.0), -90.0, 90.0);
+ lon_ = ossim::wrap(lon_ + 180.0, primary_->minLon(), primary_->maxLon());
+ eyehpr_[0] = ossim::wrap(eyehpr_[0] + 180.0, -180.0, 180.0);
+ }
+ else if (lat_ < -90.0)
+ {
+ lat_ = ossim::clamp(-lat_ - 180.0, -90.0, 90.0);
+ lon_ = ossim::wrap(lon_ + 180.0, primary_->minLon(), primary_->maxLon());
+ eyehpr_[0] = ossim::wrap(eyehpr_[0] - 180.0, -180.0, 180.0);
+ }
+}
+
+double ossimPlanetNavigator::zoomScaleInput(float input) const
+{
+ return ossim::sgn(input)*input*input*(std::abs(-eyexyz_.z() - zoomScaleBaseline_));
+}
+
+void ossimPlanetNavigator::gotoLookAt(const ossimPlanetLookAt& lookInfo, bool animateFlag)
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ if(!model.valid()) return;
+ osg::Vec3d posLlh = osg::Vec3d(lookInfo.lat(), lookInfo.lon(), lookInfo.altitude());
+ osg::Matrixd eyeLsrMatrix = viewMatrix(posLlh[0], posLlh[1], posLlh[2], lookInfo.heading(), lookInfo.pitch(), lookInfo.roll());
+
+ // now let's extrude to get the eye location then match so the eye location and lookat are good.
+ osg::Vec3d eye(eyeLsrMatrix(3,0), eyeLsrMatrix(3,1), eyeLsrMatrix(3,2));
+ osg::Vec3d zAxis(eyeLsrMatrix(2,0), eyeLsrMatrix(2,1), eyeLsrMatrix(2,2));
+ eye = eye + zAxis*(lookInfo.range()/model->getNormalizationScale());
+
+ osg::Vec3d eyeLlh;
+ model->inverse(eye, eyeLlh);
+
+ // now solve the lsr matrix
+ osg::Matrixd localLsr;
+ osg::Vec3d tempHpr;
+ model->lsrMatrix(eyeLlh, localLsr);
+ mkUtils::matrixToHpr(tempHpr, localLsr, eyeLsrMatrix);
+
+ gotoLatLonElevHpr("",
+ eyeLlh[0], eyeLlh[1], eyeLlh[2],
+ tempHpr[0], tempHpr[1], tempHpr[2],
+ animateFlag);
+}
+
+void ossimPlanetNavigator::gotoLatLonElevHpr(const std::string& /*placeName*/,
+ double latitude,
+ double longitude,
+ double elevation,
+ double heading,
+ double pitch,
+ double roll,
+ bool animateFlag)
+{
+
+ if(!animateFlag)
+ {
+ setLatLonHeight(latitude, longitude, elevation);
+ setHpr(heading, pitch, roll);
+ }
+ else
+ {
+ // This routine is excessively long, should fix that.
+ // Also it helps if you have the paper at PJM's desk to understand the math.
+
+ if (!ossim::isnan(latitude) && !ossim::isnan(longitude) && !ossim::isnan(elevation) &&
+ !ossim::isnan(heading) && !ossim::isnan(pitch) && !ossim::isnan(roll))
+ {
+ // update() uses the following variables and targetMidpointLookZ_ to move us to the target
+ gotoing_ = true;
+ losLookingFlag_ = false;
+ gotoStartTime_ = osg::Timer::instance()->tick(); //SimClock::currentFrameTime();
+ targetStartLat_ = lat_;
+ targetStartLon_ = lon_;
+ targetStartLookH_ = eyehpr_[0];
+ targetStartLookP_ = eyehpr_[1];
+ targetStartLookR_ = eyehpr_[2];
+ targetLat_ = latitude;
+ targetLon_ = longitude;
+ targetLookH_ = heading;
+ targetLookP_ = pitch;
+ targetLookR_ = roll;
+ targetLookZ_ = ossim::clamp(-elevation/primary_->radius(lat_) - 1.0, zoomMin_, zoomMax_);
+ targetStartLookZ_ = eyexyz_.z();
+
+ // the rest of this computes targetMidpointLookZ_ for all cases,
+ // so we get a nice zoom every time.
+
+ // compute some stuff
+ double theta = 0.5*fov_;
+ double cosTheta = cos(osg::DegreesToRadians(theta));
+ float oldPhi = -1.0f; // init to "see whole globe"; angle from center of screen to edge of screen, angle vertex at globe center
+ double d = -eyexyz_.z();
+ double d2 = d*d;
+ double h = d*cosTheta - sqrt(d2*cosTheta*cosTheta - d2 + 1.0);
+ if (!ossim::isnan(h))
+ {
+ double l = d - 1.0;
+ double c = sqrt(l*l + h*h - 2.0*l*h*cosTheta);
+ oldPhi = 2.0*osg::RadiansToDegrees(atan(c / (2.0*sqrt(1.0 - 0.25*c*c))));
+ }
+ float angleDelta = max(fabs(targetLat_ - lat_), fabs(targetLon_ - lon_)); // cheesy
+
+ // use that stuff to discern and handle the three cases
+ if (oldPhi <= 0.0f || angleDelta < oldPhi)
+ {
+ // we can already see the target, so don't zoom anywhere.
+ targetMidpointLookZ_ = targetStartLookZ_;
+
+ }
+ else if (angleDelta < 90.0f)
+ {
+ // target on near side of earth but we're zoomed in too close to see it,
+ // so zoom out to see target
+ double phi = angleDelta + oldPhi;
+ double cosPhi = cos(osg::DegreesToRadians(phi));
+ double alpha = 180.0 - theta - phi;
+ double cosAlpha = cos(osg::DegreesToRadians(alpha));
+ double cos2Alpha = cosAlpha*cosAlpha;
+ double cos2AlphaRecip = 1.0/cos2Alpha;
+
+ // solve the quadratic to get distance
+ pair<double, double> distance = mkUtils::quadraticRoots((cosPhi*cosPhi)/cos2Alpha - 1.0, 2.0*cosPhi - 2.0*cosPhi*cos2AlphaRecip, cos2AlphaRecip - 1.0);
+ if (!ossim::isnan(distance.first))
+ {
+ targetMidpointLookZ_ = -max(distance.first, distance.second); // use higher elevation
+ }
+ else
+ {
+ targetMidpointLookZ_ = zoomMin_; // i don't think this case can happen, but if so take just us all the way out.
+ }
+
+ }
+ else
+ {
+ // target on far side of earth, so zoom out to where earth just fills screen
+ targetMidpointLookZ_ = -(-1.0/(cosTheta*cosTheta - 1.0) + 1.0);
+ }
+ }
+ else
+ {
+ targetMidpointLookZ_ = (targetStartLookZ_ + targetLookZ_)*.5;
+ }
+
+ targetMidpointLookZ_ = ossim::clamp(targetMidpointLookZ_, zoomMin_, zoomMax_);
+ }
+}
+
+osg::Matrixd ossimPlanetNavigator::viewMatrix(double lat, double lon, double hgt,
+ double h, double p, double r)const
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ if(model.valid())
+ {
+ osg::Vec3d xyz;
+ model->forward(osg::Vec3d(lat, lon, hgt),///model->getNormalizationScale()),
+ xyz);
+ return orientationLsrMatrix(lat, lon, hgt, h, p, r)*osg::Matrixd::translate(xyz[0], xyz[1], xyz[2]);
+ }
+ return osg::Matrixd();
+}
+
+void ossimPlanetNavigator::solveLookAt(double losLat, double losLon, double losHeight,
+ double& heading, double& pitch, double& roll, double& range)const
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ if(!model.valid()) return;
+ osg::Vec3d eye;
+ osg::Matrixd eyeLsrMatrix(viewMatrix());
+ osg::Matrixd losLsrMatrix(orientationLsrMatrix(losLat, losLon, losHeight,
+ 0.0, 0.0, 0.0));
+ eye[0] = eyeLsrMatrix(3,0);
+ eye[1] = eyeLsrMatrix(3,1);
+ eye[2] = eyeLsrMatrix(3,2);
+ eyeLsrMatrix(3,0) = 0.0;
+ eyeLsrMatrix(3,1) = 0.0;
+ eyeLsrMatrix(3,2) = 0.0;
+
+ osg::Vec3d tempHpr;
+ mkUtils::matrixToHpr(tempHpr, losLsrMatrix, eyeLsrMatrix);
+ osg::Vec3d eyeXyz;
+ osg::Vec3d losXyz;
+ model->forward(osg::Vec3d(losLat, losLon, losHeight),
+ losXyz);
+ range = (losXyz-eye).length()*model->getNormalizationScale();
+ heading = tempHpr[0];
+ pitch = tempHpr[1];
+ roll = tempHpr[2];
+}
+void ossimPlanetNavigator::solveEyeGivenLocalSpaceAndRange(osg::Vec3d& llh, // out lat lon height
+ osg::Vec3d& hpr, // output orientation
+ const osg::Vec3d& localLlh,
+ const osg::Vec3d& localHpr,
+ double rangeInMeters)const
+{
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = landModel();
+ osg::Matrixd m = viewMatrix(localLlh[0], localLlh[1], localLlh[2], localHpr[0], localHpr[1], localHpr[2]);
+ osg::Vec3d eye(m(3,0), m(3,1), m(3,2));
+ osg::Vec3d zAxis(m(2,0), m(2,1), m(2,2));
+ zAxis.normalize();
+
+ // now get the new eye position
+ // and solve the orientation
+ osg::Vec3d xyz = eye + zAxis*(rangeInMeters/model->getNormalizationScale());
+ model->inverse(xyz, llh);
+ osg::Matrixd newM = viewMatrix(llh[0], llh[1], llh[2], 0.0, 0.0, 0.0);
+ mkUtils::matrixToHpr(hpr, newM, m);
+}
+
+void ossimPlanetNavigator::playRecording()
+{
+ if(!theAnimationPath->getTimeControlPointMap().empty())
+ {
+ if(theAnimationMode == NAV_ANIMATION_RECORDING)
+ {
+ theAnimationPath->insert(osg::Timer::instance()->delta_s(theAnimationStartTime, osg::Timer::instance()->tick()),
+ osg::AnimationPath::ControlPoint(theLastAnimationParameter.eye,
+ theLastAnimationParameter.quat));
+
+ }
+ theAnimationMode = NAV_ANIMATION_PLAYBACK;
+ theAnimationStartTime = osg::Timer::instance()->tick();
+ rotating_ = false;
+ zooming_ = false;
+ losLookingFlag_ = false;
+ zoominglos_ = false;
+ flying_ = false;
+ }
+ else
+ {
+ theAnimationMode = NAV_ANIMATION_NONE;
+ }
+}
+
+void ossimPlanetNavigator::startRecording()
+{
+ theAnimationMode = NAV_ANIMATION_RECORDING;
+ theAnimationPath->getTimeControlPointMap().clear();
+ theAnimationStartTime = osg::Timer::instance()->tick();
+}
+
+void ossimPlanetNavigator::stopRecording()
+{
+ if(theAnimationMode == NAV_ANIMATION_RECORDING)
+ {
+ theAnimationPath->insert(osg::Timer::instance()->delta_s(theAnimationStartTime, osg::Timer::instance()->tick()),
+ osg::AnimationPath::ControlPoint(theLastAnimationParameter.eye,
+ theLastAnimationParameter.quat));
+
+ }
+ theAnimationMode = NAV_ANIMATION_NONE;
+}
+
+void ossimPlanetNavigator::saveRecording(std::ostream& out)
+{
+ if(!theAnimationPath->getTimeControlPointMap().empty())
+ {
+ theAnimationPath->write(out);
+ }
+}
+
+bool ossimPlanetNavigator::loadRecording(std::istream& in)
+{
+ theAnimationPath->getTimeControlPointMap().clear();
+ theAnimationPath->read(in);
+ return !theAnimationPath->getTimeControlPointMap().empty();
+}
+
+void ossimPlanetNavigator::setUseTimedUpdateFlag(bool flag)
+{
+ theUseTimedUpdateFlag = flag;
+}
+
+osg::ref_ptr<ossimPlanetGeoRefModel> ossimPlanetNavigator::landModel()
+{
+ if(thePlanet)
+ {
+ return thePlanet->model();
+ }
+ return 0;
+}
+const osg::ref_ptr<ossimPlanetGeoRefModel> ossimPlanetNavigator::landModel()const
+{
+ if(thePlanet)
+ {
+ return thePlanet->model();
+ }
+ return 0;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetNode.cpp
new file mode 100644
index 0000000..56da321
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetNode.cpp
@@ -0,0 +1,350 @@
+#include <ossimPlanet/ossimPlanetNode.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <osgUtil/IntersectVisitor>
+#include <osgUtil/IntersectionVisitor>
+ossimPlanetNode::ossimPlanetNode()
+:theEnableFlag(true),
+theIntersectableFlag(true),
+theRedrawFlag(false),
+theLayer(0)
+{
+ setCullCallback(new ossimPlanetTraverseCallback);
+ setUpdateCallback(new ossimPlanetTraverseCallback);
+}
+
+ossimPlanetNode::~ossimPlanetNode()
+{
+ setUpdateCallback(0);
+ setCullCallback(0);
+
+ notifyDestructing(this);
+ theCallbackList.clear();
+}
+
+void ossimPlanetNode::remove(osg::Node* node)
+{
+ osg::ref_ptr<osg::Node> savedNode = node;
+ ossim_uint32 upperIdx = node->getParents().size();
+ if(upperIdx > 0)
+ {
+ ossim_uint32 idx = 0;
+ for(;idx < upperIdx;++idx)
+ {
+ osg::Group* group = node->getParent(idx)->asGroup();
+ if(group)
+ {
+ group->removeChild(node);
+ }
+ }
+ }
+}
+
+void ossimPlanetNode::traverse(osg::NodeVisitor& nv)
+{
+ if(!theLayer)
+ {
+ setLayer(ossimPlanetLayer::findLayer(nv.getNodePath()));
+ }
+ if(!intersectFlag()&&(dynamic_cast<osgUtil::IntersectVisitor*> (&nv) ||
+ dynamic_cast<osgUtil::IntersectionVisitor*> (&nv)))
+ {
+ return;
+ }
+
+ if(!enableFlag())
+ {
+ return;
+ }
+ osg::Group::traverse(nv);
+}
+
+void ossimPlanetNode::execute(const ossimPlanetAction& action)
+{
+ const ossimPlanetXmlAction* xmlAction = action.toXmlAction();
+ if(xmlAction&&xmlAction->xmlNode().valid())
+ {
+ ossimString command = action.command();
+ if(command == "Set")
+ {
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& childNodes = xmlAction->xmlNode()->getChildNodes();
+ const ossimXmlNode::ChildListType* properties = 0;
+ // at this point we should just have a single object in the first child of the set
+ //
+ if(childNodes.size() == 1)
+ {
+ properties = &(childNodes[0]->getChildNodes());
+ }
+ if(!properties) return;
+ for(idx = 0;idx<properties->size();++idx)
+ {
+ ossimString tag = (*properties)[idx]->getTag();
+ if(tag=="name")
+ {
+ setName((*properties)[idx]->getText());
+ }
+ else if(tag == "description")
+ {
+ setDescription((*properties)[idx]->getText());
+ }
+ else if(tag == "id")
+ {
+ setId((*properties)[idx]->getText());
+ }
+ else if(tag == "receiverPath")
+ {
+ setPathnameAndRegister((*properties)[idx]->getText());
+ }
+ }
+ }
+ }
+}
+
+bool ossimPlanetNode::addChild( Node *child )
+{
+ bool result = osg::Group::addChild(child);
+
+ if(result)
+ {
+ ossimPlanetNode* layerNode = dynamic_cast<ossimPlanetNode*>(child);
+ if(layerNode) layerNode->setLayer(ossimPlanetLayer::findLayer(child));
+ notifyAddChild(child);
+ setRedrawFlag(true);
+ nodeAdded(child);
+ }
+
+ return result;
+}
+
+bool ossimPlanetNode::insertChild( unsigned int index, Node *child )
+{
+ bool result = osg::Group::insertChild(index, child);
+
+ if(result)
+ {
+ ossimPlanetNode* layerNode = dynamic_cast<ossimPlanetNode*>(child);
+ if(layerNode) layerNode->setLayer(ossimPlanetLayer::findLayer(child));
+ notifyAddChild(child);
+ setRedrawFlag(true);
+ nodeAdded(child);
+ }
+ return result;
+}
+
+bool ossimPlanetNode::replaceChild( Node *origChild, Node* newChild )
+{
+ osg::ref_ptr<osg::Node> origChildSave = origChild;
+ osg::ref_ptr<osg::Node> newChildSave = newChild;
+ bool result = osg::Group::replaceChild(origChild, newChild);
+ if(result)
+ {
+ ossimPlanetNode* layerNode = dynamic_cast<ossimPlanetNode*>(newChild);
+ if(layerNode)
+ {
+ layerNode->setLayer(ossimPlanetLayer::findLayer(this));
+ }
+ notifyAddChild(newChild);
+ notifyRemoveChild(origChild);
+ setRedrawFlag(true);
+ nodeRemoved(origChildSave.get());
+ nodeAdded(newChildSave.get());
+ }
+
+ return result;
+}
+
+bool ossimPlanetNode::removeChildren(unsigned int pos,unsigned int numChildrenToRemove)
+{
+ if (pos<getNumChildren() && numChildrenToRemove>0)
+ {
+ unsigned int endOfRemoveRange = pos+numChildrenToRemove;
+ if (endOfRemoveRange>getNumChildren())
+ {
+ endOfRemoveRange=getNumChildren();
+ }
+ osg::Node* node = 0;
+ ossim_uint32 idx = pos;
+ for(;idx<endOfRemoveRange;++idx)
+ {
+ node = getChild(idx);
+ if(node)
+ {
+ notifyRemoveChild(node);
+ nodeRemoved(node);
+ }
+ }
+ }
+ bool result = osg::Group::removeChildren(pos, numChildrenToRemove);
+ if(result)
+ {
+ setRedrawFlag(true);
+ }
+
+ return result;
+}
+
+void ossimPlanetNode::setRedrawFlag(bool flag)//(bool flag, bool passToParentFlag)
+{
+ bool changed = false;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePlanetNodeRedrawPropertyMutex);
+ changed = (theRedrawFlag != flag);
+ theRedrawFlag = flag;
+ }
+ if(flag)
+ {
+ ossimPlanetLayer* l = layer();
+ if(l&&(l!=this))
+ {
+ l->setRedrawFlag(flag);
+ }
+ }
+ if(changed&&flag)
+ {
+ notifyNeedsRedraw();
+ }
+
+#if 0
+ if(!dynamic_cast<ossimPlanetLayer*>(this))
+ {
+ if(layer())
+ {
+ layer()->setRedrawFlag(flag, passToParentFlag);
+ return;
+ }
+ }
+ bool changed = false;
+ {
+ OpenThreads::ScopedWriteLock lock(thePlanetNodeRedrawPropertyMutex);
+ changed = (theRedrawFlag != flag);
+ theRedrawFlag = flag;
+ }
+ // notify just one time on Redraw flag set to true
+ if(changed)
+ {
+ if(flag)
+ {
+ notifyNeedsRedraw();
+ }
+ if(passToParentFlag)
+ {
+ //OpenThreads::ScopedReadLock lock(thePlanetNodePropertyMutex);
+ ossim_uint32 idx = 0;
+ ossim_uint32 idxMax = getNumParents();
+ for(idx = 0; idx < idxMax; ++idx)
+ {
+ ossimPlanetNode* layerNode = dynamic_cast<ossimPlanetNode*>(getParent(idx));
+ if(layerNode)
+ {
+ layerNode->setRedrawFlag(flag, passToParentFlag);
+ }
+ }
+ }
+ }
+#endif
+}
+
+
+ossimPlanetNode* ossimPlanetNode::findNode(osg::NodePath& currentNodePath)
+{
+ if(currentNodePath.empty())
+ {
+ return 0;
+ }
+ for(osg::NodePath::reverse_iterator itr = currentNodePath.rbegin();
+ itr != currentNodePath.rend();
+ ++itr)
+ {
+ ossimPlanetNode* node = dynamic_cast<ossimPlanetNode*>(*itr);
+ if (node)
+ {
+ return node;
+ }
+ }
+
+ return 0;
+}
+
+void ossimPlanetNode::notifyPropertyChanged(ossimPlanetNode* node, const ossimString& name)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->propertyChanged(node, name);
+ }
+ }
+}
+
+void ossimPlanetNode::notifyDestructing(ossimPlanetNode* node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->destructingNode(node);
+ }
+ }
+}
+
+void ossimPlanetNode::notifyNeedsRedraw()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->needsRedraw(this);
+ }
+ }
+}
+
+void ossimPlanetNode::notifyAddChild(osg::ref_ptr<osg::Node> node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->nodeAdded(node.get());
+ }
+ }
+}
+
+void ossimPlanetNode::notifyRemoveChild(osg::ref_ptr<osg::Node> node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->nodeRemoved(node.get());
+ }
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetNodeFactory.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetNodeFactory.cpp
new file mode 100644
index 0000000..0cbdcfa
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetNodeFactory.cpp
@@ -0,0 +1,35 @@
+#include <ossimPlanet/ossimPlanetNodeFactory.h>
+#include <ossimPlanet/ossimPlanetAnnotationLayerNode.h>
+
+ossimPlanetNodeFactory* ossimPlanetNodeFactory::theInstance = 0;
+
+ossimPlanetNodeFactory::ossimPlanetNodeFactory()
+{
+ theInstance = this;
+}
+
+ossimPlanetNodeFactory::~ossimPlanetNodeFactory()
+{
+ theInstance = 0;
+}
+
+
+ossimPlanetNodeFactory* ossimPlanetNodeFactory::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetNodeFactory;
+ }
+
+ return theInstance;
+}
+
+ossimPlanetNode* ossimPlanetNodeFactory::create(const ossimString& type)const
+{
+ if(type == "Placemark")
+ {
+ return new ossimPlanetAnnotationPlacemark;
+ }
+ return 0;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetNodeRegistry.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetNodeRegistry.cpp
new file mode 100644
index 0000000..723819f
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetNodeRegistry.cpp
@@ -0,0 +1,84 @@
+#include <ossimPlanet/ossimPlanetNodeRegistry.h>
+#include <ossimPlanet/ossimPlanetNodeFactory.h>
+#include <algorithm>
+ossimPlanetNodeRegistry* ossimPlanetNodeRegistry::theInstance = 0;
+ossim_uint32 ossimPlanetNodeRegistry::theInitializeCount = 0;
+
+
+ossimPlanetNodeRegistry::ossimPlanetNodeRegistry()
+{
+ theInstance = this;
+}
+ossimPlanetNodeRegistry::~ossimPlanetNodeRegistry()
+{
+ theInstance = 0;
+}
+
+ossimPlanetNodeRegistry* ossimPlanetNodeRegistry::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetNodeRegistry;
+ theInstance->registerFactory(ossimPlanetNodeFactory::instance());
+ }
+
+ return theInstance;
+}
+
+void ossimPlanetNodeRegistry::finalize()
+{
+}
+
+ossimPlanetNode* ossimPlanetNodeRegistry::create(const ossimString& type)const
+{
+ ossimPlanetNode* layerNode = 0;
+ theFactoryListMutex.readLock();
+ FactoryListType::const_iterator iter = theFactoryList.begin();
+ while((iter != theFactoryList.end())&&(!layerNode))
+ {
+ layerNode = (*iter)->create(type);
+ ++iter;
+ }
+ theFactoryListMutex.readUnlock();
+ return layerNode;
+}
+
+bool ossimPlanetNodeRegistry::hasFactory(const ossimPlanetNodeFactoryBase* factory)const
+{
+ FactoryListType::const_iterator iter = std::find(theFactoryList.begin(),
+ theFactoryList.end(),
+ factory);
+ return (iter != theFactoryList.end());
+}
+
+void ossimPlanetNodeRegistry::registerFactory(ossimPlanetNodeFactoryBase* factory,
+ bool insertFrontFlag)
+{
+ if(!hasFactory(factory))
+ {
+ theFactoryListMutex.writeLock();
+ if(!insertFrontFlag)
+ {
+ theFactoryList.push_back(factory);
+ }
+ else
+ {
+ theFactoryList.insert(theFactoryList.begin(),
+ factory);
+ }
+ theFactoryListMutex.writeUnlock();
+ }
+}
+
+void ossimPlanetNodeRegistry::unregisterFactory(const ossimPlanetNodeFactoryBase* factory)
+{
+ theFactoryListMutex.writeLock();
+ FactoryListType::iterator iter = std::find(theFactoryList.begin(),
+ theFactoryList.end(),
+ factory);
+ if(iter!=theFactoryList.end())
+ {
+ theFactoryList.erase(iter);
+ }
+ theFactoryListMutex.writeUnlock();
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetOperation.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetOperation.cpp
new file mode 100644
index 0000000..383523c
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetOperation.cpp
@@ -0,0 +1,652 @@
+#include <ossimPlanet/ossimPlanetOperation.h>
+#include <iostream>
+#include <algorithm>
+const ossimPlanetOperation::Priority ossimPlanetOperation::PRIORITY_HIGHEST = 1.0/DBL_EPSILON;
+const ossimPlanetOperation::Priority ossimPlanetOperation::PRIORITY_LOWEST = 0.0;
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperation::nextDependency(bool recurseFlag)
+{
+ osg::ref_ptr<ossimPlanetOperation> result;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theDependencyListMutex);
+ if(!recurseFlag)
+ {
+ if(theDependencyList.size()>0)
+ {
+ result = *theDependencyList.begin();
+ theDependencyList.erase(theDependencyList.begin());
+ }
+ }
+ else if(theDependencyList.size()>0)
+
+ {
+
+ osg::ref_ptr<ossimPlanetOperation> prevOperation = (*theDependencyList.begin()).get();
+ osg::ref_ptr<ossimPlanetOperation> currentOperation = prevOperation;
+
+ if(currentOperation.valid())
+ {
+ while(currentOperation->hasDependency())
+ {
+ prevOperation = currentOperation;
+ currentOperation = (*currentOperation->dependencyList().begin()).get();
+ }
+ result = currentOperation;
+ prevOperation->dependencyList().erase(prevOperation->dependencyList().begin());
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetOperation::notifyReady()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->ready(this);
+ }
+ }
+}
+void ossimPlanetOperation::notifyStarted()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->started(this);
+ }
+ }
+}
+
+void ossimPlanetOperation::notifyFinished()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->finished(this);
+ }
+ }
+}
+
+
+void ossimPlanetOperation::notifyCanceled()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->canceled(this);
+ }
+ }
+}
+
+void ossimPlanetOperation::notifyPriorityChanged()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->priorityChanged(this);
+ }
+ }
+}
+
+void ossimPlanetOperation::notifyPropertyChanged(const ossimString& name)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->propertyChanged(name, this);
+ }
+ }
+}
+
+ossimPlanetOperationQueue::ossimPlanetOperationQueue()
+{
+ setThreadSafeRefUnref(true);
+ theBlock = new ossimPlanetRefBlock;
+}
+
+ossimPlanetOperationQueue::~ossimPlanetOperationQueue()
+{
+}
+
+void ossimPlanetOperationQueue::add(ossimPlanetOperation* operation, bool guaranteeUniqueFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+
+ if(guaranteeUniqueFlag)
+ {
+ if(findByPointer(operation) != theOperationQueue.end())
+ {
+ theBlock->set(true);
+ return;
+ }
+ }
+ theOperationQueue.push_back(operation);
+
+ theBlock->set(true);
+}
+
+void ossimPlanetOperationQueue::removeStoppedOperations()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ ossimPlanetOperation::List::iterator iter = theOperationQueue.begin();
+ while(iter!=theOperationQueue.end())
+ {
+ if((*iter)->isStopped())
+ {
+ iter = theOperationQueue.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationQueue::removeById(const ossimString& id)
+{
+ osg::ref_ptr<ossimPlanetOperation> result;
+ if(id.empty()) return result;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ ossimPlanetOperation::List::iterator iter = findById(id);
+ if(iter!=theOperationQueue.end())
+ {
+ result = *iter;
+ theOperationQueue.erase(iter);
+ }
+
+ theBlock->set(!theOperationQueue.empty());
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationQueue::removeByName(const ossimString& name)
+{
+ osg::ref_ptr<ossimPlanetOperation> result;
+ if(name.empty()) return result;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ ossimPlanetOperation::List::iterator iter = findByName(name);
+ if(iter!=theOperationQueue.end())
+ {
+ result = *iter;
+ theOperationQueue.erase(iter);
+ }
+
+ theBlock->set(!theOperationQueue.empty());
+
+ return result;
+}
+
+void ossimPlanetOperationQueue::remove(const ossimPlanetOperation* operation)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ ossimPlanetOperation::List::iterator iter = findByPointer(operation);
+ if(iter!=theOperationQueue.end())
+ {
+ theOperationQueue.erase(iter);
+ }
+
+ theBlock->set(!theOperationQueue.empty());
+}
+
+void ossimPlanetOperationQueue::removeAllOperations()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ theOperationQueue.clear();
+ theBlock->set(false);
+}
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationQueue::nextOperation(bool blockIfEmptyFlag)
+{
+ theOperationQueueMutex.lock();
+ bool emptyFlag = theOperationQueue.empty();
+ theOperationQueueMutex.unlock();
+ if (blockIfEmptyFlag && emptyFlag)
+ {
+ theBlock->block();
+ }
+ osg::ref_ptr<ossimPlanetOperation> result;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+
+ if (theOperationQueue.empty())
+ {
+ theBlock->set(false);
+ return result;
+ }
+
+ ossimPlanetOperation::List::iterator iter= theOperationQueue.begin();
+ while((iter != theOperationQueue.end())&&
+ (((*iter)->isStopped())))
+ {
+ iter = theOperationQueue.erase(iter);
+ }
+ if(iter != theOperationQueue.end())
+ {
+ result = *iter;
+ theOperationQueue.erase(iter);
+ }
+ theBlock->set(!theOperationQueue.empty());
+ return result;
+}
+
+ossimPlanetOperation::List::iterator ossimPlanetOperationQueue::findById(const ossimString& id)
+{
+ if(id.empty()) return theOperationQueue.end();
+ ossimPlanetOperation::List::iterator iter = theOperationQueue.begin();
+ while(iter != theOperationQueue.end())
+ {
+ if(id == (*iter)->id())
+ {
+ return iter;
+ }
+ ++iter;
+ }
+ return theOperationQueue.end();
+}
+
+ossimPlanetOperation::List::iterator ossimPlanetOperationQueue::findByName(const ossimString& name)
+{
+ if(name.empty()) return theOperationQueue.end();
+ ossimPlanetOperation::List::iterator iter = theOperationQueue.begin();
+ while(iter != theOperationQueue.end())
+ {
+ if(name == (*iter)->name())
+ {
+ return iter;
+ }
+ ++iter;
+ }
+ return theOperationQueue.end();
+}
+
+ossimPlanetOperation::List::iterator ossimPlanetOperationQueue::findByPointer(const ossimPlanetOperation* operation)
+{
+ return std::find(theOperationQueue.begin(),
+ theOperationQueue.end(),
+ operation);
+}
+
+ossimPlanetOperation::List::iterator ossimPlanetOperationQueue::findByNameOrPointer(const ossimPlanetOperation* operation)
+{
+ ossimString n = operation->name();
+ ossimPlanetOperation::List::iterator iter = theOperationQueue.begin();
+ while(iter != theOperationQueue.end())
+ {
+ if((*iter).get() == operation)
+ {
+ return iter;
+ }
+ else if((!n.empty())&&
+ (operation->name() == (*iter)->name()))
+ {
+ return iter;
+ }
+ ++iter;
+ }
+
+ return theOperationQueue.end();
+}
+
+bool ossimPlanetOperationQueue::hasOperation(ossimPlanetOperation* operation)
+{
+ ossimPlanetOperation::List::const_iterator iter = theOperationQueue.begin();
+ while(iter != theOperationQueue.end())
+ {
+ if(operation == (*iter).get())
+ {
+ return true;
+ }
+ ++iter;
+ }
+
+ return false;
+}
+
+
+void ossimPlanetOperationQueue::releaseOperationsBlock()
+{
+ theBlock->release();
+}
+
+bool ossimPlanetOperationQueue::empty()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ return theOperationQueue.empty();
+}
+
+
+struct SortRequestFunctor
+{
+ bool operator() (const osg::ref_ptr<ossimPlanetOperation>& lhs,
+ const osg::ref_ptr<ossimPlanetOperation>& rhs) const
+ {
+ return (lhs->priority()>rhs->priority());
+ }
+};
+
+ossimPlanetOperationPriorityQueue::ossimPlanetOperationPriorityQueue()
+{
+}
+
+ossimPlanetOperationPriorityQueue::~ossimPlanetOperationPriorityQueue()
+{
+
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationPriorityQueue::nextOperation(bool blockIfEmptyFlag)
+{
+ // we will sort the queue and let the base pop the first element and process
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+
+ theOperationQueue.sort(SortRequestFunctor());
+ }
+
+ return ossimPlanetOperationQueue::nextOperation(blockIfEmptyFlag);
+}
+
+ossimPlanetOperationThreadQueue::ossimPlanetOperationThreadQueue(ossimPlanetOperationQueue* opq)
+: osg::Referenced(true),
+ theDoneFlag(false),
+ theOperationQueue(opq)
+{
+ if(!theOperationQueue.valid())
+ {
+ theOperationQueue = new ossimPlanetOperationQueue();
+ }
+}
+
+ossimPlanetOperationThreadQueue::~ossimPlanetOperationThreadQueue()
+{
+ cancel();
+}
+
+void ossimPlanetOperationThreadQueue::setOperationQueue(ossimPlanetOperationQueue* opq)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+
+ if (theOperationQueue == opq) return;
+
+ theOperationQueue = opq;
+}
+
+void ossimPlanetOperationThreadQueue::setDone(bool done)
+{
+ if (theDoneFlag==done) return;
+
+ theDoneFlag = done;
+
+ if(theDoneFlag)
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if (theCurrentOperation.valid())
+ {
+ theCurrentOperation->release();
+ }
+ }
+
+ if (theOperationQueue.valid()) theOperationQueue->releaseOperationsBlock();
+ }
+}
+
+
+int ossimPlanetOperationThreadQueue::cancel()
+{
+ int result = 0;
+
+ removeAllOperations();
+
+ if( isRunning() )
+ {
+
+ theDoneFlag = true;
+
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if (theCurrentOperation.valid())
+ {
+ theCurrentOperation->cancel();
+ }
+
+ if (theOperationQueue.valid())
+ {
+ theOperationQueue->releaseOperationsBlock();
+ }
+
+ if (theOperationQueue.valid()) theOperationQueue->releaseOperationsBlock();
+ }
+
+ // then wait for the the thread to stop running.
+ while(isRunning())
+ {
+
+#if 1
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+
+ if (theOperationQueue.valid())
+ {
+ theOperationQueue->releaseOperationsBlock();
+ // _operationQueue->releaseAllOperations();
+ }
+
+ if (theOperationQueue.valid()) theOperationQueue->releaseOperationsBlock();
+ }
+#endif
+ OpenThreads::Thread::YieldCurrentThread();
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetOperationThreadQueue::add(ossimPlanetOperation* operation, bool guaranteeUniqueFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ osg::ref_ptr<ossimPlanetOperation> op = operation;
+ if (!theOperationQueue) return;
+ theOperationQueue->add(op.get(), guaranteeUniqueFlag);
+ if(!isRunning())
+ {
+ start();
+ while(!isRunning())
+ {
+ OpenThreads::Thread::YieldCurrentThread();
+ }
+ }
+}
+
+void ossimPlanetOperationThreadQueue::remove(ossimPlanetOperation* operation)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if (theOperationQueue.valid()) theOperationQueue->remove(operation);
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationThreadQueue::removeByName(const ossimString& name)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if (theOperationQueue.valid()) return theOperationQueue->removeByName(name);
+
+ return 0;
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationThreadQueue::removeById(const ossimString& id)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if (theOperationQueue.valid()) return theOperationQueue->removeById(id);
+
+ return 0;
+}
+
+void ossimPlanetOperationThreadQueue::removeAllOperations()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if (theOperationQueue.valid())
+ {
+ theOperationQueue->removeAllOperations();
+ }
+}
+
+void ossimPlanetOperationThreadQueue::cancelCurrentOperation()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ if(theCurrentOperation.valid())
+ {
+ theCurrentOperation->cancel();
+ }
+}
+
+void ossimPlanetOperationThreadQueue::run()
+{
+ bool firstTime = true;
+
+ do
+ {
+ // osg::notify(osg::NOTICE)<<"In thread loop "<<this<<std::endl;
+ osg::ref_ptr<ossimPlanetOperation> operation;
+ osg::ref_ptr<ossimPlanetOperationQueue> queue;
+
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ queue = theOperationQueue;
+ }
+
+ operation = nextOperation();
+
+ if (theDoneFlag) break;
+
+ if (operation.valid())
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ theCurrentOperation = operation;
+ }
+
+ while(operation->hasDependency())
+ {
+ osg::ref_ptr<ossimPlanetOperation> dependency = operation->nextDependency();
+ if(!operation->isStopped())
+ {
+ dependency->start();
+ }
+ }
+ if(!operation->isStopped())
+ {
+ operation->start();
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ theCurrentOperation = 0;
+ }
+ }
+
+ if (firstTime)
+ {
+ // do a yield to get round a peculiar thread hang when testCancel() is called
+ // in certain cirumstances - of which there is no particular pattern.
+ YieldCurrentThread();
+ firstTime = false;
+ }
+ } while (!testCancel() && !theDoneFlag);
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationThreadQueue::nextOperation()
+{
+ return theOperationQueue->nextOperation(true);
+}
+
+ossimPlanetOperationMultiThreadQueue::ossimPlanetOperationMultiThreadQueue(ossim_uint32 numberOfThreads)
+:theOperationQueue(new ossimPlanetOperationQueue)
+{
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < numberOfThreads;++idx)
+ {
+ ossimPlanetOperationThreadQueue* threadQueue = new ossimPlanetOperationThreadQueue(theOperationQueue.get());
+ threadQueue->start();
+ theThreadQueueList.push_back(threadQueue);
+ }
+}
+
+ossimPlanetOperationMultiThreadQueue::~ossimPlanetOperationMultiThreadQueue()
+{
+ removeAllOperations();
+ cancelCurrentOperation();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theThreadQueueList.size();++idx)
+ {
+ theThreadQueueList[idx]->cancel();
+ }
+ theThreadQueueList.clear();
+}
+
+ossimPlanetOperationQueue* ossimPlanetOperationMultiThreadQueue::operationQueue()
+{
+ return theOperationQueue.get();
+}
+
+/** Get the const OperationQueue. */
+const ossimPlanetOperationQueue* ossimPlanetOperationMultiThreadQueue::operationQueue() const
+{
+ return theOperationQueue.get();
+}
+
+void ossimPlanetOperationMultiThreadQueue::add(ossimPlanetOperation* operation, bool guaranteeUniqueFlag)
+{
+ theOperationQueue->add(operation, guaranteeUniqueFlag);
+}
+
+/** Remove operation from OperationQueue.*/
+void ossimPlanetOperationMultiThreadQueue::remove(ossimPlanetOperation* operation)
+{
+ theOperationQueue->remove(operation);
+}
+
+/** Remove named operation from OperationQueue.*/
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationMultiThreadQueue::removeByName(const ossimString& name)
+{
+ return theOperationQueue->removeByName(name);
+}
+/** Remove named operation from OperationQueue.*/
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetOperationMultiThreadQueue::removeById(const ossimString& id)
+{
+ return theOperationQueue->removeById(id);
+}
+
+/** Remove all operations from OperationQueue.*/
+void ossimPlanetOperationMultiThreadQueue::removeAllOperations()
+{
+ theOperationQueue->removeAllOperations();
+}
+
+void ossimPlanetOperationMultiThreadQueue::cancelCurrentOperation()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theThreadQueueList.size();++idx)
+ {
+ theThreadQueueList[idx]->cancelCurrentOperation();
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetOssimElevationDatabase.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetOssimElevationDatabase.cpp
new file mode 100644
index 0000000..b82843f
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetOssimElevationDatabase.cpp
@@ -0,0 +1,355 @@
+#include <ossimPlanet/ossimPlanetOssimElevationDatabase.h>
+#include <ossimPlanet/ossimPlanetGrid.h>
+
+ossimPlanetOssimElevationDatabase::ossimPlanetOssimElevationDatabase()
+:ossimPlanetElevationDatabase()
+{
+}
+
+ossimPlanetOssimElevationDatabase::ossimPlanetOssimElevationDatabase(const ossimPlanetOssimElevationDatabase& src)
+:ossimPlanetElevationDatabase(src),
+m_cellDatabaseFlag(src.m_cellDatabaseFlag),
+m_database(src.m_database)
+{
+}
+
+ossimPlanetOssimElevationDatabase::~ossimPlanetOssimElevationDatabase()
+{
+}
+
+ossimPlanetTextureLayer* ossimPlanetOssimElevationDatabase::dup()const
+{
+ return new ossimPlanetOssimElevationDatabase(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetOssimElevationDatabase::dupType()const
+{
+ return new ossimPlanetOssimElevationDatabase();
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimElevationDatabase::updateExtents()
+{
+ ossimPlanetTextureLayerStateCode result = ossimPlanetTextureLayer_VALID;
+ if(m_database.valid())
+ {
+ theExtents = new ossimPlanetExtents;
+ ossim_float64 meanGsd = m_database->getMeanSpacingMeters();
+
+ if(ossim::isnan(meanGsd))
+ {
+
+ theExtents->setMinMaxScale(meanGsd, meanGsd*64);//pow(2.0, 5.0));
+ }
+ }
+ else
+ {
+ result = ossimPlanetTextureLayer_NOT_OPENED;
+ }
+ theDirtyExtentsFlag = false;
+ return result;
+}
+
+void ossimPlanetOssimElevationDatabase::updateStats()const
+{
+ theStats->setTotalTextureSize(0);
+ theDirtyStatsFlag = false;
+}
+
+void ossimPlanetOssimElevationDatabase::resetStats()const
+{
+ theStats->setBytesTransferred(0);
+ theStats->setTotalTextureSize(0);
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimElevationDatabase::open(const std::string& location)
+{
+ return ossimPlanetTextureLayer_NOT_OPENED;
+}
+
+bool ossimPlanetOssimElevationDatabase::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ if(!theEnableFlag||!theExtents.valid())
+ {
+ return false;
+ }
+ ossimPlanetGrid::GridBound bound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ ossimPlanetGrid::GridBound tileBound;
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return false;
+ }
+ }
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ ossimPlanetGrid::ModelPoint minLatLon, maxLatLon;
+ grid.modelBound(tileId, minLatLon, maxLatLon);
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetOssimElevationDatabase::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+
+ if(!theExtents.valid()) return 0;
+
+ if(m_cellDatabaseFlag&&!grid.isPolar(tileId))
+ {
+ return getTextureCellDatabase(width, height, tileId, grid, padding);
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ double minValue = 999999999.0;
+ double maxValue = -999999999.0;
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ double h = m_database->getHeightAboveEllipsoid(ossimGpt((*optimizedOutPtr).y(), (*optimizedOutPtr).x()));
+ if(!ossim::isnan(h))
+ {
+ *bufPtr = h;
+ }
+
+ ++bufPtr;
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+
+ return texture;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetOssimElevationDatabase::getTextureCellDatabase(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+
+{
+ ossimElevationCellDatabase* cellElevationDatabase = (ossimElevationCellDatabase*)m_database.get();
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+// std::cout << "EXTENTS CHECK = " << gsd.y << " < " << theExtents->getMaxScale() << std::endl;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ ossim_float64 minModelX, minModelY, maxModelX, maxModelY;
+ minModelX = points[0].x();
+ maxModelX = minModelX;
+ minModelY = points[0].y();
+ maxModelY = minModelY;
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ ++optimizedOutPtr;
+ for(idxPts = 1; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if(optimizedOutPtr->x() < minModelX) minModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->x() > maxModelX) maxModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->y() < minModelY) minModelY = optimizedOutPtr->y();
+ if(optimizedOutPtr->y() > maxModelY) maxModelY = optimizedOutPtr->y();
+ }
+ ossim_int32 wholeMinY = (ossim_int32)std::floor(minModelY);
+ ossim_int32 wholeMinX = (ossim_int32)std::floor(minModelX);
+ ossim_int32 wholeMaxY = (ossim_int32)std::floor(maxModelY);
+ ossim_int32 wholeMaxX = (ossim_int32)std::floor(maxModelX);
+ ossim_int32 lat = wholeMaxY;
+ ossim_int32 lon = wholeMinX;
+
+ std::vector<ossimGpt> latLonOrigins;
+
+ for(;lat >= wholeMinY; --lat)
+ {
+ lon = wholeMinX;
+ for(;lon <= wholeMaxX; ++lon)
+ {
+ ossimGpt gpt(lat, lon);
+ if(m_database->pointHasCoverage(gpt))
+ {
+ latLonOrigins.push_back(gpt);
+ }
+ }
+ }
+
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/DBL_EPSILON -1;
+ double maxValue = -1.0/DBL_EPSILON +1;
+ if(latLonOrigins.size() == 0)
+ {
+ return 0;
+ }
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfFilesNeeded = latLonOrigins.size();
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ ossim_uint32 numberNeeded = latLonOrigins.size();
+ for(idx = 0; idx < numberNeeded;++idx)
+ {
+ ossimRefPtr<ossimElevCellHandler> cellHandler = cellElevationDatabase->getOrCreateCellHandler(latLonOrigins[idx]);
+ if(cellHandler.valid())
+ {
+ ossimGrect grect = cellHandler->getBoundingGndRect();
+ ossim_float64 minLat = grect.ll().latd();
+ ossim_float64 minLon = grect.ll().lond();
+ ossim_float64 maxLat = grect.ur().latd();
+ ossim_float64 maxLon = grect.ur().lond();
+ ossim_float64 nullHeight = cellHandler->getNullHeightValue();
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ optimizedOutPtr = &points.front();
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&
+ (optimizedOutPtr->y() >= minLat)&&
+ (optimizedOutPtr->y() <= maxLat)&&
+ (optimizedOutPtr->x() >= minLon)&&
+ (optimizedOutPtr->x() <= maxLon))
+ {
+ double h = cellHandler->getHeightAboveMSL(ossimGpt(optimizedOutPtr->y(),
+ optimizedOutPtr->x()));
+ if(!ossim::isnan(h)&&
+ (h!=nullHeight))
+ {
+ if(theGeoRefModel.valid())
+ {
+ h+=theGeoRefModel->getGeoidOffset(optimizedOutPtr->y(), optimizedOutPtr->x());
+ }
+ *bufPtr = h;
+ if(h < minValue)
+ {
+ minValue = h;
+ }
+ if(h > maxValue)
+ {
+ maxValue = h;
+ }
+ }
+ }
+ ++bufPtr;
+ }
+ }
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+
+ return texture;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetOssimImage.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetOssimImage.cpp
new file mode 100644
index 0000000..53634a8
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetOssimImage.cpp
@@ -0,0 +1,43 @@
+#include <ossimPlanet/ossimPlanetOssimImage.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+ossimPlanetOssimImage::ossimPlanetOssimImage()
+{
+}
+ossimPlanetOssimImage::~ossimPlanetOssimImage()
+{
+}
+
+bool ossimPlanetOssimImage::loadFile(const std::string& inputFile,
+ ossimPlanetImage& image)
+{
+ if(theHandler.valid())
+ {
+ theHandler->close();
+ if(!theHandler->open(ossimFilename(inputFile)))
+ {
+ theHandler = 0;
+ }
+ }
+ ossimRefPtr<ossimImageData> data;
+ if(!theHandler.valid())
+ {
+ theHandler = ossimImageHandlerRegistry::instance()->open(ossimFilename(inputFile.c_str()));
+ }
+ if(theHandler.valid())
+ {
+ data = theHandler->getTile(theHandler->getBoundingRect());
+ if(data.valid())
+ {
+ image.fromOssimImage(data);
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetOssimImageLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetOssimImageLayer.cpp
new file mode 100644
index 0000000..be25f28
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetOssimImageLayer.cpp
@@ -0,0 +1,1374 @@
+#include <ossimPlanet/ossimPlanetOssimImageLayer.h>
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimBandSelector.h>
+#include <ossim/imaging/ossimScalarRemapper.h>
+#include <ossim/imaging/ossimNitfTileSource.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/support_data/ossimNitfImageHeader.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimImageViewTransform.h>
+#include <ossim/projection/ossimImageViewProjectionTransform.h>
+#include <ossim/imaging/ossimFilterResampler.h>
+#include <ossim/imaging/ossimCacheTileSource.h>
+#include <ossim/imaging/ossimMeanMedianFilter.h>
+#include <ossimPlanet/mkUtils.h>
+#include <osg/io_utils>
+ossimPlanetOssimImageLayer::ossimPlanetOssimImageLayer()
+:theCut(0),
+ossimPlanetTextureLayer(),
+theHistogramRemapper(0),
+theHistogramStretchMode(ossimHistogramRemapper::STRETCH_UNKNOWN),
+theHistogramStretchEnableFlag(false),
+theCenterLat(0.0),
+theCenterLon(0.0),
+theLength(0.0)
+{
+ theViewInterface = 0;
+ theStateCode = ossimPlanetTextureLayer_NOT_OPENED;
+}
+
+ossimPlanetOssimImageLayer::ossimPlanetOssimImageLayer(const ossimPlanetOssimImageLayer& src)
+:ossimPlanetTextureLayer(src),
+theCut(0),
+theFilename(src.theFilename),
+theCenterLat(src.theCenterLat),
+theCenterLon(src.theCenterLon)
+{
+ theHistogramRemapper = 0;
+ if(src.theSource.valid())
+ {
+ theSource = (ossimImageHandler*)src.theSource->dup();
+ }
+ theViewInterface = 0;
+ theRenderer = 0;
+ theChain.clear();
+ theImageSpaceChain.clear();
+ theProjection = 0;
+ buildChain();
+}
+
+ossimPlanetOssimImageLayer::~ossimPlanetOssimImageLayer()
+{
+ if(theSource.valid())
+ {
+ theSource->disconnect();
+ theSource = 0;
+ }
+ theRenderer = 0;
+ clearChains();
+}
+void ossimPlanetOssimImageLayer::clearChains()
+{
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theChain.size(); ++idx)
+ {
+ theChain[idx]->disconnect();
+ theChain[idx] = 0;
+ }
+ theChain.clear();
+ for(idx = 0; idx < theImageSpaceChain.size(); ++idx)
+ {
+ theImageSpaceChain[idx]->disconnect();
+ theImageSpaceChain[idx] = 0;
+ }
+ theImageSpaceChain.clear();
+
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimImageLayer::openImage(const ossimFilename& filename,
+ ossim_int32 entryIdx)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ theViewInterface = 0;
+ theFilename = "";
+ theSource = 0;
+ theRenderer = 0;
+ theCenterLat = 0.0;
+ theCenterLon = 0.0;
+ theLength = 0.0;
+ theHistogramRemapper = 0;
+ theStateCode = ossimPlanetTextureLayer_VALID;
+
+ ossimRefPtr<ossimImageHandler> source = (ossimImageHandlerRegistry::instance()->open(filename));
+ if(theOverviewFile.exists()&&source.valid())
+ {
+ source->openOverview(theOverviewFile);
+ }
+ if(source.valid()&&(entryIdx > -1))
+ {
+ if(!source->setCurrentEntry(entryIdx))
+ {
+ setState(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ return theStateCode;
+ }
+ }
+ else if(!source.valid())
+ {
+ setState(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ return theStateCode;
+ }
+ setState (setHandler(source) );
+ return theStateCode;
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimImageLayer::setCurrentEntry(ossim_int32 idx)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ theViewInterface = 0;
+ theRenderer = 0;
+ theCenterLat = 0.0;
+ theCenterLon = 0.0;
+ theLength = 0.0;
+ theHistogramRemapper = 0;
+ theStateCode = ossimPlanetTextureLayer_VALID;
+
+ if(theSource.valid())
+ {
+ if(!theSource->setCurrentEntry(idx))
+ {
+ setState(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ return theStateCode;
+ }
+ }
+ else
+ {
+ setState(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ return theStateCode;
+ }
+ if(theOverviewFile.exists()&&theSource.valid())
+ {
+ theSource->openOverview(theOverviewFile);
+ }
+ setState(setHandler(theSource.get()));
+ return theStateCode;
+}
+
+ossim_uint32 ossimPlanetOssimImageLayer::getNumberOfEntries()const
+{
+ if(theSource.valid())
+ {
+ return theSource->getNumberOfEntries();
+ }
+
+ return 0;
+}
+
+void ossimPlanetOssimImageLayer::setOverviewFile(const ossimFilename& filename)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ theOverviewFile = filename;
+ if(theSource.valid())
+ {
+ if(theOverviewFile.exists())
+ {
+ if(theSource->openOverview(theOverviewFile))
+ {
+ clearState(ossimPlanetTextureLayer_NO_OVERVIEWS);
+ }
+ }
+ else
+ {
+ theSource->closeOverview();
+ }
+ dirtyExtents();
+ }
+ notifyPropertyChanged("overviewFilename", this);
+ }
+ if(filename.exists())
+ {
+ notifyRefreshExtent(theExtents.get());
+ }
+}
+
+void ossimPlanetOssimImageLayer::setHistogramFile(const ossimFilename& file)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ theHistogramFile = file;
+ if(theHistogramRemapper)
+ {
+ if(theHistogramRemapper->openHistogram(file))
+ {
+ theHistogramRemapper->setStretchMode(theHistogramStretchMode);
+ clearState(ossimPlanetTextureLayer_NO_HISTOGRAMS);
+ }
+ dirtyExtents();
+ }
+ notifyPropertyChanged("histogramFilename", this);
+ }
+ if(file.exists())
+ {
+ notifyRefreshExtent(theExtents.get());
+ }
+}
+
+void ossimPlanetOssimImageLayer::setHistogramStretchMode(const ossimString& mode)
+{
+ bool changed = false;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+
+ if(mode == "None")
+ {
+ theHistogramStretchMode = ossimHistogramRemapper::STRETCH_UNKNOWN;
+ }
+ else if(mode == "Linear Auto Min Max")
+ {
+ theHistogramStretchMode = ossimHistogramRemapper::LINEAR_AUTO_MIN_MAX;
+ }
+ else if(mode == "1 Standard Deviation")
+ {
+ theHistogramStretchMode = ossimHistogramRemapper::LINEAR_1STD_FROM_MEAN;
+ }
+ else if(mode == "2 Standard Deviation")
+ {
+ theHistogramStretchMode = ossimHistogramRemapper::LINEAR_2STD_FROM_MEAN;
+ }
+ else if(mode == "3 Standard Deviation")
+ {
+ theHistogramStretchMode = ossimHistogramRemapper::LINEAR_3STD_FROM_MEAN;
+ }
+ else
+ {
+ theHistogramStretchMode = ossimHistogramRemapper::STRETCH_UNKNOWN;
+ }
+ if(theHistogramRemapper)
+ {
+ changed = theHistogramRemapper->getStretchMode() != theHistogramStretchMode;
+ theHistogramRemapper->setStretchMode(theHistogramStretchMode);
+ }
+ }
+ if(changed)
+ {
+ notifyRefreshExtent(theExtents.get());
+ }
+}
+
+void ossimPlanetOssimImageLayer::setHistogramStretchEnableFlag(bool flag)
+{
+ bool changed = false;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ if(theHistogramRemapper)
+ {
+ theHistogramStretchEnableFlag = flag;
+ if(flag != theHistogramRemapper->getEnableFlag())
+ {
+ theHistogramRemapper->setEnableFlag(theHistogramStretchEnableFlag);
+ changed = true;
+ }
+ }
+ }
+ if(changed)
+ {
+ notifyRefreshExtent(theExtents.get());
+ }
+}
+
+ossimString ossimPlanetOssimImageLayer::histogramStretchMode()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ switch(theHistogramStretchMode)
+ {
+ case ossimHistogramRemapper::STRETCH_UNKNOWN:
+ {
+ return "None";
+ }
+ case ossimHistogramRemapper::LINEAR_AUTO_MIN_MAX:
+ {
+ return "Linear Auto Min Max";
+ }
+ case ossimHistogramRemapper::LINEAR_1STD_FROM_MEAN:
+ {
+ return "1 Standard Deviation";
+ }
+ case ossimHistogramRemapper::LINEAR_2STD_FROM_MEAN:
+ {
+ return "2 Standard Deviation";
+ }
+ case ossimHistogramRemapper::LINEAR_3STD_FROM_MEAN:
+ {
+ return "3 Standard Deviation";
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return "None";
+}
+
+void ossimPlanetOssimImageLayer::getHistogramStretchModes(std::vector<ossimString>& modes)
+{
+ modes.push_back("None");
+ modes.push_back("Linear Auto Min Max");
+ modes.push_back("1 Standard Deviation");
+ modes.push_back("2 Standard Deviation");
+ modes.push_back("3 Standard Deviation");
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimImageLayer::setHandler(ossimRefPtr<ossimImageHandler> handler)
+{
+ theFilename = "";
+ theSource = handler;
+ theRenderer = 0;
+ theCenterLat = 0.0;
+ theCenterLon = 0.0;
+ theLength = 0.0;
+
+ if(handler.valid())
+ {
+ theFilename = handler->getFilename();
+ if(name().empty())
+ {
+ ossimString name = theFilename.file();
+
+ if(handler->getNumberOfEntries() > 1)
+ {
+ name += ": entry " + ossimString::toString(handler->getCurrentEntry());
+ }
+ setName(name);
+ }
+ }
+
+ return buildChain();
+}
+
+ossimRefPtr<ossimImageHandler> ossimPlanetOssimImageLayer::getHandler()
+{
+ return theSource;
+}
+
+const ossimRefPtr<ossimImageHandler> ossimPlanetOssimImageLayer::getHandler()const
+{
+ return theSource;
+}
+
+double ossimPlanetOssimImageLayer::getApproximateHypotneusLength()const
+{
+ return theLength;
+}
+
+ossimPlanetTextureLayer* ossimPlanetOssimImageLayer::dup()const
+{
+ return new ossimPlanetOssimImageLayer(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetOssimImageLayer::dupType()const
+{
+ return new ossimPlanetOssimImageLayer;
+}
+
+ossimString ossimPlanetOssimImageLayer::getClassName()const
+{
+ return "ossimPlanetOssimImageLayer";
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimImageLayer::updateExtents()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ return updateExtentsNoMutex();
+}
+ossimPlanetTextureLayerStateCode ossimPlanetOssimImageLayer::updateExtentsNoMutex()
+{
+ if(!theDirtyExtentsFlag) return theStateCode;
+
+ clearState(ossimPlanetTextureLayerStateCode(ossimPlanetTextureLayer_NO_OVERVIEWS |
+ ossimPlanetTextureLayer_NO_GEOM |
+ ossimPlanetTextureLayer_NO_SOURCE_DATA));
+ theCenterLat = 0.0;
+ theCenterLon = 0.0;
+ theLength = 0.0;
+ theInputProjection = 0;
+ if(theSource.valid())
+ {
+ double levels = theSource->getNumberOfDecimationLevels();
+ ossimRefPtr<ossimImageGeometry> geom = theSource->getImageGeometry();
+ theInputProjection = geom.valid()?geom->getProjection():0;
+ if(levels == 1)
+ {
+ setState(ossimPlanetTextureLayer_NO_OVERVIEWS);
+ }
+
+ if(theInputProjection.valid())
+ {
+
+ ossimGpt ulGpt;
+ ossimGpt urGpt;
+ ossimGpt lrGpt;
+ ossimGpt llGpt;
+ ossimGpt centerGpt;
+
+ ossimIrect rect = theSource->getBoundingRect();
+ geom->localToWorld(rect.midPoint(),
+ centerGpt);
+ theCenterLat = centerGpt.latd();
+ theCenterLon = centerGpt.lond();
+
+ geom->localToWorld(rect.ul(),
+ ulGpt);
+ geom->localToWorld(rect.ur(),
+ urGpt);
+ geom->localToWorld(rect.lr(),
+ lrGpt);
+ geom->localToWorld(rect.ll(),
+ llGpt);
+ ossimDpt metersPerPixel = geom->getMetersPerPixel();
+ theLength = ((rect.ul()-rect.lr()).length()*
+ (metersPerPixel.y));
+
+ ossim_uint32 levels = theSource->getNumberOfDecimationLevels();
+ ossim_uint32 stopLevels = levels;
+ ossim_uint32 idx = 0;
+#if 1
+ for(idx = 0; idx < levels; ++idx)
+ {
+ ossimIrect rect = theSource->getBoundingRect(idx);
+ if((rect.width()>16)||(rect.height()>16))
+ {
+ ++stopLevels;
+ }
+ else
+ {
+ break;
+ }
+ }
+#endif
+ theExtents->setMinMaxScale(metersPerPixel.y,
+ metersPerPixel.y*std::pow(2.0, (double)(stopLevels)));// clamp the zoom out though
+ theExtents->setMinMaxLatLon(mkUtils::clamp(ossim::min(ulGpt.latd(),ossim::min(urGpt.latd(),ossim::min(lrGpt.latd(),llGpt.latd()))), -90.0, 90.0),
+ mkUtils::clamp(ossim::min(ulGpt.lond(),ossim::min(urGpt.lond(),ossim::min(lrGpt.lond(),llGpt.lond()))), -180.0, 180.0),
+ mkUtils::clamp(ossim::max(ulGpt.latd(),ossim::max(urGpt.latd(),ossim::max(lrGpt.latd(),llGpt.latd()))), -90.0, 90.0),
+ mkUtils::clamp(ossim::max(ulGpt.lond(),ossim::max(urGpt.lond(),ossim::max(lrGpt.lond(),llGpt.lond()))), -180.0, 180.0));
+
+// std::cout << theExtents->getMinLon() << ", " << theExtents->getMinLat() << ", " << theExtents->getMaxLon() << ", " << theExtents->getMaxLat() << std::endl;
+ }
+ else
+ {
+ setState(ossimPlanetTextureLayer_NO_GEOM);
+ }
+ }
+ else
+ {
+ setState(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ }
+ theDirtyExtentsFlag = false;
+ updateStats();
+
+
+ return theStateCode;
+}
+
+void ossimPlanetOssimImageLayer::updateStats()const
+{
+ if(theSource.valid())
+ {
+ ossimIrect rect = theSource->getBoundingRect();
+ ossim_uint64 bands = theSource->getNumberOfInputBands();
+ ossimScalarType scalarType = theSource->getOutputScalarType();
+ ossim_uint64 w = rect.width();
+ ossim_uint64 h = rect.height();
+ ossim_uint64 scalarSizeInBytes = ossim::scalarSizeInBytes(scalarType);
+ theStats->setTotalTextureSize(scalarSizeInBytes*w*h*bands);
+
+ if(theSource->getNumberOfDecimationLevels()>1)
+ {
+ ossim_uint32 levels = theSource->getNumberOfDecimationLevels();
+ ossim_uint32 idx = 0;
+ for(idx=1; idx < levels; ++idx)
+ {
+ rect = theSource->getBoundingRect(idx);
+ w = rect.width();
+ h = rect.height();
+ theStats->setTotalTextureSize(theStats->totalTextureSize() +
+ scalarSizeInBytes*w*h*bands);
+
+ }
+ }
+ }
+ theDirtyStatsFlag = false;
+}
+
+void ossimPlanetOssimImageLayer::resetStats()const
+{
+ updateStats();
+ theStats->setBytesTransferred(0);
+}
+
+ossimScalarType ossimPlanetOssimImageLayer::scalarType()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ if(theSource.valid())
+ {
+ return theSource->getOutputScalarType();
+ }
+
+ return OSSIM_SCALAR_UNKNOWN;
+}
+
+bool ossimPlanetOssimImageLayer::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ if(!getEnableFlag())
+ {
+ return false;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ if(!theInputProjection.valid() ||
+ !theSource.valid())
+ {
+ return false;
+ }
+ osg::Vec2d metersPerPixel;
+ grid.getUnitsPerPixel(metersPerPixel, tileId, width, height, OSSIM_METERS);
+ ossimDpt metersGsd(metersPerPixel[0], metersPerPixel[1]);
+ if(theExtents.valid())
+ {
+ osg::ref_ptr<ossimPlanetExtents> extents = new ossimPlanetExtents;
+ if(grid.convertToGeographicExtents(tileId, *extents, width, height))
+ {
+ if(theExtents->intersectsLatLon(*extents)&&
+ theExtents->intersectsScale(*extents))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetOssimImageLayer::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 /*padding*/)
+{
+ if(!getEnableFlag())
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ if(!theInputProjection.valid() ||
+ !theSource.valid())
+ {
+ return 0;
+ }
+
+ osg::ref_ptr<ossimPlanetExtents> tileExtents = new ossimPlanetExtents;
+ if(grid.convertToGeographicExtents(tileId, *tileExtents, width, height))
+ {
+ if(theExtents.valid())
+ {
+ if(!theExtents->intersectsLatLon(*tileExtents))
+ {
+ return 0;
+ }
+ }
+ }
+ osg::Vec2d unitsPerPixel;
+ osg::Vec2d metersPerPixel;
+ grid.getUnitsPerPixel(unitsPerPixel, tileId, width, height, OSSIM_DEGREES);
+ grid.getUnitsPerPixel(metersPerPixel, tileId, width, height, OSSIM_METERS);
+ ossimDpt gsd(unitsPerPixel[0], unitsPerPixel[1]);
+ ossimDpt metersGsd(metersPerPixel[0], metersPerPixel[1]);
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+
+ if(metersGsd.y < theExtents->getMaxScale())
+ {
+// std::cout << "LEVEL === " << tileId.level() << std::endl;
+ if(!grid.isPolar(tileId))
+ {
+ ossimIrect requestRect(0,
+ 0,
+ width-1,
+ height-1);
+// theProjection->setDecimalDegreesPerPixel(ossimDpt(deltaLon,
+// deltaLat));
+ ossimGpt testUl(tileExtents->getMaxLat()-(gsd.y*.5),
+ tileExtents->getMinLon()+(gsd.x*.5));
+ theProjection->setDecimalDegreesPerPixel(ossimDpt(gsd.x,
+ gsd.y));
+ theProjection->setUlTiePoints(testUl);
+ theProjection->update();
+ theViewInterface->setView(theImageGeometry.get());
+ theChain[0]->initialize();
+
+ ossimRefPtr<ossimImageData> data;
+ data = theChain[0]->getTile(requestRect);
+
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ addBytesTransferredStat(data->getSizeInBytes());
+ texture = new ossimPlanetImage(tileId);
+ convertToOsg(data.get(), texture.get());
+ texture->flipVertical();
+ }
+ }
+ else
+ {
+ // std::cout << "________________________" << std::endl;
+ ossimPlanetGrid::ModelPoints modelPoints;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ modelPoints);
+
+ //std::cout << "NEW WAY" << std::endl;
+ std::vector<osg::Vec2d> minMaxPairs;
+ grid.getInternationalDateLineCrossings(tileId, minMaxPairs);
+ ossim_uint32 size = minMaxPairs.size();
+ ossim_uint32 idx = 0;
+ double maxLon=0.0, minLon=0.0, maxLat=tileExtents->getMaxLat(), minLat=tileExtents->getMinLat();
+ for(idx = 0; idx < size; ++idx)
+ {
+ minLon = minMaxPairs[idx][0];
+ maxLon = minMaxPairs[idx][1];
+
+ ossim_uint32 dx = (ossim_uint32)(((maxLon-minLon)/gsd.x));//+.5);
+ ossim_uint32 dy = (ossim_uint32)(((maxLat-minLat)/gsd.y));//+.5);
+ ossimIrect requestRect(0,
+ 0,
+ dx-1,
+ dy-1);
+ ossimRefPtr<ossimImageData> data;
+
+ ossim_float32 tiles = (double)requestRect.width()/(double)width;
+ ossim_uint32 nTiles = floor((double)requestRect.width()/(double)width);
+ ossim_float32 residualTile = tiles - nTiles;
+ ossim_uint32 tileX = 0;
+ theProjection->setDecimalDegreesPerPixel(gsd);
+#if 0
+ theProjection->setUlTiePoints(ossimGpt(maxLat-(gsd.y*.5),
+ minLon+(gsd.x*.5)));
+ theViewInterface->setView(theImageGeometry.get());
+ data = theChain[0]->getTile(requestRect);
+ theChain->initialize();
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ addBytesTransferredStat(data->getSizeInBytes());
+ if(!texture.valid())
+ {
+ texture = new ossimPlanetImage(tileId);
+ }
+
+ convertToOsg(data.get(),
+ texture.get(),
+ osg::Vec2d(minLon,
+ maxLat),
+ osg::Vec2d(maxLon,//deltaLon,
+ maxLat),
+ osg::Vec2d(maxLon,//deltaLon,
+ minLat),//deltaLat),
+ osg::Vec2d(minLon,
+ minLat),//deltaLat),
+ modelPoints,
+ width,
+ height);
+
+ }
+#else
+ for(tileX = 0; tileX < nTiles; ++tileX)
+ {
+ ossimIpt origin(tileX*width, 0);
+ ossimIrect tempRect(0, 0, width - 1, dy-1);
+
+ double tempMinLon = minLon + gsd.x*(origin.x);
+ double tempMaxLon = tempMinLon + gsd.x*width;
+ theProjection->setUlTiePoints(ossimGpt(maxLat-(gsd.y*.5),
+ tempMinLon+(gsd.x*.5)));
+ theViewInterface->setView(theImageGeometry.get());
+ theChain[0]->initialize();
+ data = theChain[0]->getTile(tempRect);
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ if(!texture.valid())
+ {
+ texture = new ossimPlanetImage(tileId);
+ }
+
+ convertToOsg(data.get(),
+ texture.get(),
+ osg::Vec2d(tempMinLon,
+ maxLat),
+ osg::Vec2d(tempMaxLon,//deltaLon,
+ maxLat),
+ osg::Vec2d(tempMaxLon,//deltaLon,
+ minLat),//deltaLat),
+ osg::Vec2d(tempMinLon,
+ minLat),//deltaLat),
+ modelPoints,
+ width,
+ height);
+
+ }
+ data = 0;
+ }
+ if(residualTile > FLT_EPSILON)
+ {
+ ossim_uint32 w = (residualTile*width);
+ ossimIpt origin(nTiles*width, 0);
+ ossimIrect tempRect(0, 0, w - 1, dy-1);
+ double tempMinLon = minLon + gsd.x*(origin.x);
+ double tempMaxLon = maxLon;
+ theProjection->setUlTiePoints(ossimGpt(maxLat,//-(deltaLat*.5),
+ tempMinLon));//+(deltaLon*.5)));
+ theViewInterface->setView(theImageGeometry.get());
+ theChain[0]->initialize();
+ data = theChain[0]->getTile(tempRect);
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ if(!texture.valid())
+ {
+ texture = new ossimPlanetImage(tileId);
+ if(texture->data())
+ {
+ memset(texture->data(), '\0', texture->getWidth()*texture->getHeight()*4);
+ }
+ }
+
+ convertToOsg(data.get(),
+ texture.get(),
+ osg::Vec2d(tempMinLon,
+ maxLat),
+ osg::Vec2d(tempMaxLon,//deltaLon,
+ maxLat),
+ osg::Vec2d(tempMaxLon,//deltaLon,
+ minLat),//deltaLat),
+ osg::Vec2d(tempMinLon,
+ minLat),//deltaLat),
+ modelPoints,
+ width,
+ height);
+
+ }
+ data = 0;
+ }
+#endif
+ }
+ }
+ }
+ return texture;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetOssimImageLayer::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ if(!getEnableFlag())
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(theOssimImageLayerMutex);
+
+ if(!theProjection.valid() ||
+ !theSource.valid())
+ {
+ return 0;
+ }
+
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+ unsigned int w = utility.getTileWidth();
+ unsigned int h = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row, // row
+ col);
+ if(!theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ return 0;
+ }
+
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/h;
+ double deltaLon = deltaX/w;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ if(utility.getFace(level, row, col)<4)
+ {
+ ossimIrect requestRect(0,
+ 0,
+ w-1,
+ h-1);
+ theProjection->setDecimalDegreesPerPixel(ossimDpt(deltaLon,
+ deltaLat));
+
+ theProjection->setUlGpt(ossimGpt(maxLat-deltaLat*.5, minLon+deltaLon*.5));
+ //theProjection->setUlGpt(ossimGpt(maxLat, minLon));
+ theViewInterface->setView(theImageGeometry.get());
+ ossimRefPtr<ossimImageData> data;
+ data = theChain[0]->getTile(requestRect);
+
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ addBytesTransferredStat(data->getSizeInBytes());
+ texture = new ossimPlanetImage(ossimPlanetTerrainTileId(0,
+ level,
+ col,
+ row));
+ convertToOsg(data.get(), texture.get());
+ texture->flipVertical();
+ }
+ }
+ else
+ {
+ // std::cout << "________________________________" << std::endl;
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ utility.createGridPoints(points,
+ level,
+ row,
+ col,
+ w,
+ h);
+ osg::Vec3d llTemp;
+ utility.getLatLon(llTemp, points[0]);
+
+ std::vector<osg::Vec2d> minMaxPairs;
+ utility.getGeographicLonCrossings(minMaxPairs, level, row, col);
+
+ ossim_uint32 size = minMaxPairs.size();
+ ossim_uint32 idx = 0;
+ //std::cout << "OLD WAY!" << std::endl;
+ for(idx = 0; idx < size; ++idx)
+ {
+ minLon = minMaxPairs[idx][0];
+ maxLon = minMaxPairs[idx][1];
+ //std::cout << "minLon = " << minLon << std::endl;
+ //std::cout << "maxLon = " << maxLon << std::endl;
+
+ ossim_uint32 dx = (ossim_uint32)(((maxLon-minLon)/deltaLon));//+.5);
+ ossim_uint32 dy = (ossim_uint32)(((maxLat-minLat)/deltaLat));//+.5);
+ ossimDpt degreesPerPixel(deltaLon,
+ deltaLat);
+ //std::cout << "degrees per pix = " << degreesPerPixel << std::endl;
+ theProjection->setDecimalDegreesPerPixel(degreesPerPixel);
+ theProjection->setUlGpt(ossimGpt(maxLat-deltaLat*.5, minLon+deltaLon*.5));
+ // theProjection->setUlGpt(ossimGpt(maxLat, minLon));
+ //std::cout << "Ul tie = " << ossimGpt(maxLat, minLon) << std::endl;
+ theViewInterface->setView(theImageGeometry.get());
+ ossimIrect requestRect(0,
+ 0,
+ dx-1,
+ dy-1);
+ ossimRefPtr<ossimImageData> data;
+ data = theChain[0]->getTile(requestRect);
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ addBytesTransferredStat(data->getSizeInBytes());
+ if(!texture.valid())
+ {
+ texture = new ossimPlanetImage(ossimPlanetTerrainTileId(0,
+ level,
+ col,
+ row));
+ }
+
+ convertToOsg(data.get(),
+ texture.get(),
+ osg::Vec2d(minLon,
+ maxLat),
+ osg::Vec2d(maxLon+deltaLon,
+ maxLat),
+ osg::Vec2d(maxLon+deltaLon,
+ minLat-deltaLat),
+ osg::Vec2d(minLon,
+ minLat-deltaLat),
+ points,
+ utility,
+ w,
+ h);
+
+ }
+ }
+ }
+ }
+ return texture;
+}
+
+void ossimPlanetOssimImageLayer::getCenterLatLonLength(double& centerLat,
+ double& centerLon,
+ double& length)const
+{
+ centerLat = theCenterLat;
+ centerLon = theCenterLon;
+ length = theLength;
+}
+
+void ossimPlanetOssimImageLayer::setFilterType(const ossimString& filterType)
+{
+ ossimPlanetTextureLayer::setFilterType(filterType);
+ if(theRenderer.valid())
+ {
+ theRenderer->getResampler()->setFilterType(theFilterType);
+ }
+}
+
+bool ossimPlanetOssimImageLayer::isMultiEntry()const
+{
+ if(theSource.valid())
+ {
+ return (theSource->getNumberOfEntries() > 1);
+ }
+
+ return false;
+}
+
+bool ossimPlanetOssimImageLayer::buildOverview()
+{
+ if(theSource.valid())
+ {
+ return theSource->buildOverview();
+ }
+
+ return false;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetOssimImageLayer::groupAllEntries()
+{
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> groupResult = new ossimPlanetTextureLayerGroup;
+ if(theSource.valid())
+ {
+ ossim_uint32 thisEntry = theSource->getCurrentEntry();
+ std::vector<ossim_uint32> entryList;
+ theSource->getEntryList(entryList);
+
+ for(ossim_uint32 idx = 0; idx < entryList.size(); ++idx)
+ {
+ if(entryList[idx] != thisEntry)
+ {
+ osg::ref_ptr<ossimPlanetOssimImageLayer> layer = new ossimPlanetOssimImageLayer;
+ ossimRefPtr<ossimImageHandler> handler = (ossimImageHandler*)theSource->dup();
+ handler->setCurrentEntry(entryList[idx]);
+ layer->setHandler(handler.get());
+ layer->dirtyExtents();
+ layer->updateExtents();
+ groupResult->addBottom(layer.get());
+ }
+ }
+
+ groupResult->addTop(this);
+ }
+ return groupResult.get();
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetOssimImageLayer::buildChain()
+{
+ clearChains();
+ theHistogramRemapper = 0;
+ if(theSource.valid())
+ {
+ theChain.push_back(theSource.get());
+ //ossimMeanMedianFilter* expand = new ossimMeanMedianFilter;
+ //expand->setEnableFlag(true);
+ //expand->setWindowSize(3);
+ //expand->setFilterType(ossimMeanMedianFilter::OSSIM_MEAN_NULL_CENTER_ONLY);
+ //expand->setAutoGrowRectFlag(true);
+ //expand->connectMyInputTo(0, theChain[0].get());
+ //theChain.insert(theChain.begin(), expand);
+ if(theSource->getNumberOfOutputBands() > 3)
+ {
+ std::vector<ossim_uint32> outputBandList;
+ outputBandList.push_back(0);
+ outputBandList.push_back(1);
+ outputBandList.push_back(2);
+ ossimBandSelector* bandSelector = new ossimBandSelector;
+ bandSelector->setOutputBandList(outputBandList);
+ bandSelector->connectMyInputTo(0, theChain[0].get());
+ theChain.insert(theChain.begin(), bandSelector);
+ theImageSpaceChain.insert(theImageSpaceChain.begin(), bandSelector);
+ }
+ else if(theSource->getNumberOfOutputBands() <3)
+ {
+ std::vector<ossim_uint32> outputBandList;
+ outputBandList.push_back(0);
+ outputBandList.push_back(0);
+ outputBandList.push_back(0);
+ ossimBandSelector* bandSelector = new ossimBandSelector;
+ bandSelector->setOutputBandList(outputBandList);
+ bandSelector->connectMyInputTo(0, theChain[0].get());
+
+ theChain.insert(theChain.begin(), bandSelector);
+ theImageSpaceChain.insert(theImageSpaceChain.begin(), bandSelector);
+ }
+ theHistogramRemapper = new ossimHistogramRemapper;
+ theHistogramRemapper->connectMyInputTo(0, theChain[0].get());
+ if(theHistogramFile.empty())
+ {
+ theHistogramFile = theSource->createDefaultHistogramFilename();
+ }
+ if(theHistogramFile.exists())
+ {
+ theHistogramRemapper->openHistogram(theHistogramFile);
+ }
+ else
+ {
+ setState(ossimPlanetTextureLayer_NO_HISTOGRAMS);
+ }
+ theHistogramRemapper->setStretchMode(theHistogramStretchMode);
+ theHistogramRemapper->setEnableFlag(theHistogramStretchEnableFlag);
+ theChain.insert(theChain.begin(), theHistogramRemapper);
+ theImageSpaceChain.insert(theImageSpaceChain.begin(), theHistogramRemapper);
+ theViewInterface = PTR_CAST(ossimViewInterface, theSource.get());
+ theImageGeometry = new ossimImageGeometry();
+
+ ossimRefPtr<ossimRectangleCutFilter> theCut = new ossimRectangleCutFilter();
+ theCut->setRectangle(theSource->getBoundingRect());
+ theCut->connectMyInputTo(0, theChain[0].get());
+ theChain.insert(theChain.begin(), theCut.get());
+
+
+ theProjection = new ossimLlxyProjection;
+ // theProjection = new ossimEquDistCylProjection;
+
+ theImageGeometry->setProjection(theProjection.get());
+ if(!theViewInterface)
+ {
+ theRenderer = new ossimImageRenderer;
+ theViewInterface = theRenderer.get();
+ theRenderer->setView(theImageGeometry.get());
+ theRenderer->getResampler()->setFilterType(theFilterType);
+
+ theRenderer->connectMyInputTo(0, theChain[0].get());
+ theChain.insert(theChain.begin(), theRenderer.get());
+ ossimImageViewTransform* ivt = theRenderer->getImageViewTransform();
+ if(ivt)
+ {
+ ossimImageViewProjectionTransform* projectionTransform = PTR_CAST(ossimImageViewProjectionTransform,
+ ivt);
+ if(projectionTransform)
+ {
+ ossimRefPtr<ossimImageGeometry> geom = projectionTransform->getImageGeometry();
+ if(geom.valid())
+ {
+ ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection,
+ geom->getProjection());
+ if(mapProj)
+ {
+ mapProj->setElevationLookupFlag(false);
+ theProjection->setElevationLookupFlag(false);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ theViewInterface->setView(theImageGeometry.get());
+ }
+ if(theSource->getOutputScalarType() != OSSIM_UINT8)
+ {
+ ossimScalarRemapper* scalarRemapper = new ossimScalarRemapper;
+ scalarRemapper->connectMyInputTo(0, theChain[0].get());
+ theChain.insert(theChain.begin(), scalarRemapper);
+ ossimScalarRemapper* scalarRemapper2 = new ossimScalarRemapper;
+ scalarRemapper2->connectMyInputTo(0, theImageSpaceChain[0].get());
+ theImageSpaceChain.insert(theImageSpaceChain.begin(), scalarRemapper2);
+ }
+// theImageSpaceChain.insert(theImageSpaceChain.begin(), expand);
+ dirtyExtents();
+ updateExtentsNoMutex();
+ }
+ return theStateCode;
+}
+
+void ossimPlanetOssimImageLayer::getMetadata(ossimRefPtr<ossimXmlNode> metadata)const
+{
+ if(theSource.valid())
+ {
+ ossimScalarType scalarType = theSource->getOutputScalarType();
+ metadata->setTag("Layer");
+ metadata->addChildNode("entry",
+ ossimString::toString(theSource->getCurrentEntry()));
+ metadata->addChildNode("url",
+ ossimString("file://") + ossimString(theSource->getFilename()));
+ metadata->addChildNode("bits", ossimString::toString(ossim::scalarSizeInBytes(scalarType)*8));
+ ossimString scalarTypeString = ossimScalarTypeLut::instance()->getEntryString((ossim_int32)scalarType);
+ scalarTypeString = scalarTypeString.substitute("ossim_", "");
+ metadata->addChildNode("scalar", scalarTypeString);
+ metadata->addChildNode("PyramidLevels",
+ ossimString::toString(theSource->getNumberOfDecimationLevels()));
+ ossim_uint32 idx = 0;
+ ossim_uint32 idxMax = theSource->getNumberOfInputBands();
+ ossimRefPtr<ossimXmlNode> bandListNode = new ossimXmlNode();
+
+ bandListNode->setTag("Bands");
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode();
+ node->setTag("Count");
+ node->setText(ossimString::toString(idxMax));
+
+ bandListNode->addChildNode(node.get());
+ metadata->addChildNode(bandListNode.get());
+ for(idx = 0; idx < idxMax; ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> bandNode = new ossimXmlNode();
+ bandNode->setTag("Band");
+ bandNode->setText(ossimString::toString(idx));
+ bandNode->addChildNode("min", ossimString::toString(theSource->getMinPixelValue(idx)));
+ bandNode->addChildNode("max", ossimString::toString(theSource->getMaxPixelValue(idx)));
+ bandNode->addChildNode("null", ossimString::toString(theSource->getNullPixelValue(idx)));
+
+ bandListNode->addChildNode(bandNode.get());
+ }
+
+ std::vector<ossimRefPtr<ossimProperty> > properties;
+ theSource->getPropertyList(properties);
+
+ ossimRefPtr<ossimXmlNode> nativeProperties = new ossimXmlNode;
+
+ nativeProperties->setTag("NativeProperties");
+
+ for(idx = 0; idx < properties.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> xmlNode = properties[idx]->toXml();
+ if(xmlNode.valid())
+ {
+ nativeProperties->addChildNode(xmlNode.get());
+ }
+ }
+
+ metadata->addChildNode(nativeProperties.get());
+
+ ossimRefPtr<ossimXmlNode> modelNode = new ossimXmlNode();
+
+ modelNode->setTag("Model");
+ ossimKeywordlist kwl;
+ ossimRefPtr<ossimImageGeometry> geom = theSource->getImageGeometry();
+ if(geom.valid())
+ {
+ if(geom->getProjection())
+ {
+ geom->getProjection()->saveState(kwl);
+ }
+ ossimKeywordlist::KeywordMap::const_iterator iter = kwl.getMap().begin();
+ while(iter != kwl.getMap().end())
+ {
+ ossimRefPtr<ossimXmlNode> modelChildNode = new ossimXmlNode();
+ modelChildNode->setTag(iter->first);
+ modelChildNode->setText(iter->second);
+ modelNode->addChildNode(modelChildNode.get());
+ ++iter;
+ }
+ ossimString type = kwl.find(ossimKeywordNames::TYPE_KW);
+
+ type = type.substitute("ossim", "");
+
+ modelNode->setText(type);
+ }
+ metadata->addChildNode(modelNode.get());
+ }
+
+}
+
+ossimRefPtr<ossimXmlNode> ossimPlanetOssimImageLayer::saveXml(bool /*recurseFlag*/)const
+{
+ ossimRefPtr<ossimXmlNode> result = ossimPlanetTextureLayer::saveXml();
+
+ result->addChildNode("filename", theFilename);
+ if(theSource.valid())
+ {
+ result->addChildNode("entry", ossimString::toString(theSource->getCurrentEntry()));
+ }
+ if(!theOverviewFile.empty())
+ {
+ result->addChildNode("overviewFilename", theOverviewFile);
+ }
+ result->addChildNode("histogramStretchMode", histogramStretchMode());
+ result->addChildNode("histogramStretchEnabled", ossimString::toString(theHistogramStretchEnableFlag));
+
+ return result;
+}
+
+bool ossimPlanetOssimImageLayer::loadXml(ossimRefPtr<ossimXmlNode> node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOssimImageLayerMutex);
+ blockCallbacks(true);
+ bool result = false;
+ ossimRefPtr<ossimXmlNode> filenameNode = node->findFirstNode("filename");
+ ossimRefPtr<ossimXmlNode> overviewFilenameNode = node->findFirstNode("overviewFilename");
+ ossimRefPtr<ossimXmlNode> entryNode = node->findFirstNode("entry");
+ ossimRefPtr<ossimXmlNode> histogramStretchMode = node->findFirstNode("histogramStretchMode");
+ ossimRefPtr<ossimXmlNode> histogramStretchEnabled = node->findFirstNode("histogramStretchEnabled");
+ if(overviewFilenameNode.valid())
+ {
+ setOverviewFile(ossimFilename(overviewFilenameNode->getText()));
+ }
+ else
+ {
+ setOverviewFile(ossimFilename(""));
+ }
+ result = ossimPlanetTextureLayer::loadXml(node);
+ if(histogramStretchEnabled.valid())
+ {
+ theHistogramStretchEnableFlag = histogramStretchEnabled->getText().toBool();
+ }
+ if(filenameNode.valid()&&result)
+ {
+ ossimFilename filename(filenameNode->getText());
+ ossim_int32 entryIdx = -1;
+
+ if(entryNode.valid())
+ {
+ entryIdx = entryNode->getText().toInt32();
+ }
+
+ openImage(filename, entryIdx);
+ result = !isStateSet(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ }
+ else
+ {
+ setState(ossimPlanetTextureLayer_NO_SOURCE_DATA);
+ result = false;
+ }
+ if(histogramStretchMode.valid())
+ {
+ setHistogramStretchMode(histogramStretchMode->getText());
+ }
+ blockCallbacks(false);
+ notifyPropertyChanged("stateCode", this);
+ return result;
+}
+
+void ossimPlanetOssimImageLayer::initializeResamplePoints(const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_uint32 tileWidth,
+ ossim_uint32 tileHeight,
+ ResampleCorners& corners)
+{
+ ossimPlanetGrid::GridBound tileBound;
+ grid.bounds(tileId, tileBound);
+ ossimDrect tileBoundDrect = tileBound.toDrect();
+
+ // need to add elevation lookups if the projection is affected by elevation
+ // We will do that in a bit after we get it working
+ //
+ // counter clockwise right handed lower left origin. This will be openGL style texture
+ // ordering where 0, 0 is lower left
+ //
+ ossimPlanetGrid::ModelPoint p1, p2, p3, p4;
+ grid.globalGridToModel(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.ll().x,
+ tileBoundDrect.ll().y),
+ p1);
+ grid.globalGridToModel(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.lr().x,
+ tileBoundDrect.lr().y),
+ p2);
+ grid.globalGridToModel(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.ur().x,
+ tileBoundDrect.ur().y),
+ p3);
+ grid.globalGridToModel(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.ul().x,
+ tileBoundDrect.ul().y),
+ p4);
+
+ ossimDpt imagePoint1, imagePoint2, imagePoint3, imagePoint4;
+ theInputProjection->worldToLineSample(ossimGpt(p1.y(), p1.x()),
+ imagePoint1);
+ theInputProjection->worldToLineSample(ossimGpt(p2.y(), p2.x()),
+ imagePoint2);
+ theInputProjection->worldToLineSample(ossimGpt(p3.y(), p3.x()),
+ imagePoint3);
+ theInputProjection->worldToLineSample(ossimGpt(p4.y(), p4.x()),
+ imagePoint4);
+
+ osg::Vec2d gsd;
+ grid.widthHeightInModelSpace(tileId, gsd);
+ gsd[0]/=tileWidth;
+ gsd[1]/=tileHeight;
+ ossimDpt mpd = ossimGpt().metersPerDegree();
+ gsd[0] *= mpd.x;
+ gsd[1] *= mpd.y;
+
+ ossimDpt metersPerPixel = theInputProjection->getMetersPerPixel();
+ ossimDpt decimationFactor;
+ decimationFactor.x = (metersPerPixel.y/gsd[0] + metersPerPixel.y/gsd[1])*.5;
+ decimationFactor.y = decimationFactor.x;
+ //double levels = theSource->getNumberOfDecimationLevels();
+
+ double factor = 1.0;
+ ossim_uint32 resLevel = 0;
+ if(decimationFactor.x < 1.0)
+ {
+ // always use the higher level for now
+ while(factor*.5 > decimationFactor.x)
+ {
+ factor *= .5;
+ ++resLevel;
+ }
+ }
+ ResamplePoint resample1(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.ll().x,
+ tileBoundDrect.ll().y),
+ p1,
+ imagePoint1,
+ ossimDpt(0.0,0.0),
+ decimationFactor,
+ resLevel);
+
+ ResamplePoint resample2(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.lr().x,
+ tileBoundDrect.lr().y),
+ p2,
+ imagePoint2,
+ ossimDpt(tileWidth-1,0),
+ decimationFactor,
+ resLevel);
+ ResamplePoint resample3(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.ur().x,
+ tileBoundDrect.ur().y),
+ p3,
+ imagePoint3,
+ ossimDpt(tileWidth-1,tileHeight-1),
+ decimationFactor,
+ resLevel);
+ ResamplePoint resample4(ossimPlanetGrid::GridPoint(tileId.face(),
+ tileBoundDrect.ul().x,
+ tileBoundDrect.ul().y),
+ p4,
+ imagePoint4,
+ ossimDpt(0,tileHeight-1),
+ decimationFactor,
+ resLevel);
+
+
+ corners.push(ResampleCorner(resample1, resample2, resample3, resample4));
+
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetPagedLandLod.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetPagedLandLod.cpp
new file mode 100644
index 0000000..a755d80
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetPagedLandLod.cpp
@@ -0,0 +1,505 @@
+#include <ossimPlanet/ossimPlanetPagedLandLod.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+#include <osg/Geode>
+//#include <ossimPlanet/ossimPlanetDatabasePager.h>
+#include <osgUtil/CullVisitor>
+
+//#define OSGPLANET_ENABLE_ALLOCATION_COUNT
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static ossim_uint32 allocated = 0;
+#endif
+
+void ossimPlanetPagedLandLodCullNode::traverse(osg::NodeVisitor& nv)
+{
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ theCulledFlag = false;
+ if(!cullVisitor||!theBoundingBox.valid()) return;
+
+
+ osg::Vec3d eye = cullVisitor->getEyeLocal();
+ osg::Vec3d eyeDirection = cullVisitor->getLookVectorLocal();
+ const osg::Polytope& frustum = cullVisitor->getCurrentCullingSet().getFrustum();
+ theEyeDistance = (eye-theBoundingBox->center()).length();
+ if(theUseClusterCulling)
+ {
+ if(theClusterCullingDeviation >= -1.0)
+ {
+ osg::Vec3d eyeCp = eye - theClusterCullingControlPoint;
+ double radius = eyeCp.length();
+
+ if (radius>=theClusterCullingRadius)
+ {
+
+ double deviation = (eyeCp * theClusterCullingNormal)/radius;
+
+
+ theCulledFlag = (deviation < theClusterCullingDeviation);
+ }
+ }
+ }
+ if(!theCulledFlag)
+ {
+ if(theBoundingBox->isInFront(eye, eyeDirection))
+ {
+ theCulledFlag = !theBoundingBox->intersects(frustum);
+ }
+ else
+ {
+ theCulledFlag = true;
+ }
+ }
+}
+
+class ossimPlanetPagedLandLodTextureVisitor : public osg::NodeVisitor
+{
+public:
+ ossimPlanetPagedLandLodTextureVisitor(osg::ref_ptr<ossimPlanetLandTextureRequest> tex,
+ ossimPlanetPagedLandLod* lod)
+ :osg::NodeVisitor(NODE_VISITOR,
+ TRAVERSE_ALL_CHILDREN),
+ theRequest(tex),
+ theLod(lod),
+ theHasTextureFlag(false)
+ {
+ }
+ virtual void apply(osg::Geode& node)
+ {
+ theHasTextureFlag = false;
+ if(node.getNumDrawables() > 0)
+ {
+ osg::Geometry* geom = (node.getDrawable(0)->asGeometry());
+ if(geom)
+ {
+ osg::StateSet* dstate = geom->getOrCreateStateSet();
+ if(dstate)
+ {
+ ossim_uint32 size = dstate->getTextureAttributeList().size();
+ ossim_uint32 idx = 0;
+ // first remove all texture states befoe adding the new states.
+ for(idx = 0; idx < size; ++idx)
+ {
+ dstate->removeTextureAttribute(idx,
+ osg::StateAttribute::TEXTURE);
+ }
+ std::vector<osg::ref_ptr<osg::Texture2D> >& textures = theRequest->getTextures();
+ if(textures.size())
+ {
+ for(idx = 0;idx < textures.size(); ++idx)
+ {
+ dstate->setTextureAttributeAndModes(idx, textures[idx].get(),
+ osg::StateAttribute::ON);
+ theHasTextureFlag = true;
+ }
+ }
+ else
+ {
+ theHasTextureFlag = false;
+
+ }
+ }
+ }
+ }
+ }
+
+ bool hasTexture()const
+ {
+ return theHasTextureFlag;
+ }
+protected:
+ osg::ref_ptr<ossimPlanetLandTextureRequest> theRequest;
+ ossimPlanetPagedLandLod* theLod;
+ bool theHasTextureFlag;
+};
+
+class ossimPlanetPagedLandLodUpdateCallback : public osg::NodeCallback
+{
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ ossimPlanetPagedLandLod* n = dynamic_cast<ossimPlanetPagedLandLod*>(node);
+ if(n)
+ {
+ // ossimPlanetDatabasePager* pager = dynamic_cast<ossimPlanetDatabasePager*>(nv->getDatabaseRequestHandler());
+ //OpenThreads::ScopedLock<OpenThreads::Mutex> lock(n->theMutex);
+ if(n->theRefreshType == ossimPlanetLandRefreshType_TEXTURE)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(n->thePagedLodListMutex);
+ n->thePagedLodList.clear();
+ }
+ if(n->getNumChildren() > 0)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(n->theTextureRequestMutex);
+ ossimPlanetPagedLandLodTextureVisitor visitor(n->theTextureRequest, n);
+ if(n->theTextureRequest.valid())
+ {
+ if(n->theTextureRequest->getCullCallback().valid())
+ {
+ n->setCullCallback(n->theTextureRequest->getCullCallback().get());
+ }
+ if(n->theTextureRequest->getTransform().valid())
+ {
+ n->setChild(0, n->theTextureRequest->getTransform().get());
+ n->theCulledFlag = false;
+ n->theRemoveChildrenFlag = false;
+ n->theCenterPoint = n->theTextureRequest->centerPoint();
+ n->theUlPoint = n->theTextureRequest->ulPoint();
+ n->theUrPoint = n->theTextureRequest->urPoint();
+ n->theLrPoint = n->theTextureRequest->lrPoint();
+ n->theLlPoint = n->theTextureRequest->llPoint();
+ n->theCenterNormal = n->theTextureRequest->centerNormal();
+ n->theUlNormal = n->theTextureRequest->ulNormal();
+ n->theUrNormal = n->theTextureRequest->urNormal();
+ n->theLrNormal = n->theTextureRequest->lrNormal();
+ n->theLlNormal = n->theTextureRequest->llNormal();
+// if(n->theTextureRequest->boundingBox().valid())
+// {
+// n->theCullNode->setBoundingBox(n->theTextureRequest->boundingBox().get());
+// }
+ }
+
+ n->getChild(0)->accept(visitor);
+ if(n->theTextureRequest->getTextureState() == ossimPlanetImage::ossimPlanetImageStateType_NEEDS_LOADING)
+ {
+ if(n->theRefreshType != ossimPlanetLandRefreshType_PRUNE)
+ {
+ n->theRefreshType = ossimPlanetLandRefreshType_TEXTURE;
+ }
+ }
+ else
+ {
+ n->theRefreshType = ossimPlanetLandRefreshType_NONE;
+ }
+ n->dirtyBound();
+ n->getBound();
+ n->theTextureRequest = 0;
+ ossimPlanetLand* land = n->landLayer();
+ if(land)
+ {
+ land->pagedLodModified(n);
+ }
+ }
+ }
+ ossim_uint32 numChildren = n->getNumChildren();
+ ossimPlanetLand* land = n->landLayer();
+ if(n->theRemoveChildrenFlag||
+ n->theCulledFlag||
+ n->areAllChildrenCulled()||
+ (n->theRefreshType == ossimPlanetLandRefreshType_PRUNE))
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(n->thePagedLodListMutex);
+ ossim_uint32 idx = 0;
+ if(numChildren > 1)
+ {
+ for(idx = 1; idx < numChildren;++idx)
+ {
+ if(n->getChild(idx))
+ {
+ if(land)
+ {
+ land->pagedLodRemoved(n->getChild(idx));
+ }
+#if 0
+ if(pager)
+ {
+ pager->addToDeleteList(n->getChild(idx));
+ }
+#endif
+ //osg::Group* grp = dynamic_cast<osg::Group*>(n->getChild(idx));
+ //if( grp ) pager->removeRequest( grp );
+ }
+ }
+
+ n->removeChild(1, numChildren-1);
+ }
+
+ n->thePagedLodList.clear();
+ if(numChildren > 0)
+ {
+ n->getChild(0)->accept(*nv);
+ }
+ if(n->theRefreshType == ossimPlanetLandRefreshType_PRUNE)
+ {
+ n->theRefreshType = ossimPlanetLandRefreshType_NONE;
+ }
+ return;
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(n->thePagedLodListMutex);
+ if(n->thePagedLodList.size()==4)
+ {
+ if(n->getNumChildren() == 1)
+ {
+ for( unsigned int i = 0 ; i < n->thePagedLodList.size(); i++ )
+ {
+ n->insertChild(n->getNumChildren(), n->thePagedLodList[i].get());
+ }
+
+ if(n->getNumChildren() == 5)
+ {
+ n->thePagedLodList.clear();
+ }
+ }
+ else
+ {
+ n->thePagedLodList.clear();
+ }
+ }
+ ossim_uint32 idx =0;
+ for(idx = 0; idx < n->thePagedLodList.size(); ++idx)
+ {
+ n->thePagedLodList[idx]->accept(*nv);
+ }
+ }
+
+ traverse(node, nv);
+ }
+};
+
+ossimPlanetPagedLandLod::ossimPlanetPagedLandLod(ossim_uint32 level,
+ ossim_uint32 row,
+ ossim_uint32 col,
+ const std::string& requestName)
+ :
+ theGeode(0),
+ theLevel(level),
+ theRow(row),
+ theCol(col),
+ theRequestNameList(5),
+ theCulledFlag(false),
+ theRemoveChildrenFlag(false),
+ theMaxLevel(99999999),
+ theChildCullNodeList(4)
+
+{
+ theRefreshType = ossimPlanetLandRefreshType_NONE;
+ theRequestNameList[0] = requestName;
+ setUpdateCallback( new ossimPlanetPagedLandLodUpdateCallback );
+ theCullNode = new ossimPlanetPagedLandLodCullNode();
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ ++allocated;
+ std::cout << "ossimPlanetPagedLandLod count: " << allocated << std::endl;
+#endif
+}
+
+ossimPlanetPagedLandLod::~ossimPlanetPagedLandLod()
+{
+ theGeode = 0;
+
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ --allocated;
+ std::cout << "ossimPlanetPagedLandLod count: " << allocated << std::endl;
+#endif
+}
+
+ossimPlanetPagedLandLod::ossimPlanetPagedLandLod(const ossimPlanetPagedLandLod& src,
+ const osg::CopyOp& copyop)
+ :osg::Group(src, copyop),
+ theLevel(src.theLevel),
+ theRow(src.theRow),
+ theCol(src.theCol),
+ theRequestNameList(src.theRequestNameList),
+ theCulledFlag(src.theCulledFlag),
+ theRemoveChildrenFlag(src.theRemoveChildrenFlag),
+ theChildCullNodeList(4)
+{
+}
+
+bool ossimPlanetPagedLandLod::areAllChildrenLeaves()const
+{
+ if(getNumChildren()!=5) return false;
+ ossim_uint32 idx;
+ ossim_uint32 bounds = getNumChildren();
+ for(idx = 1; idx < bounds; ++idx)
+ {
+ const ossimPlanetPagedLandLod* lod = dynamic_cast<const ossimPlanetPagedLandLod*>(getChild(idx));
+ if(lod)
+ {
+ if(!lod->isLeaf()) return false;
+ }
+ }
+
+ return true;
+}
+
+bool ossimPlanetPagedLandLod::hasCulledChildren()const
+{
+ if(getNumChildren()<2) return false;
+ ossim_uint32 idx = 0;
+ ossim_uint32 bounds = getNumChildren();
+ for(idx = 1; idx < bounds; ++idx)
+ {
+ const ossimPlanetPagedLandLod* lod = dynamic_cast<const ossimPlanetPagedLandLod*>(getChild(idx));
+ if(lod)
+ {
+ if(lod->getCulledFlag()) return true;
+ }
+ }
+
+ return false;
+}
+
+bool ossimPlanetPagedLandLod::areAllChildrenCulled(bool applyToAddedChildrenOnly)const
+{
+ if(applyToAddedChildrenOnly)
+ {
+ if(getNumChildren()!=5) return false;
+ }
+ if(getNumChildren()==1) return false;
+ ossim_uint32 idx = 0;
+ ossim_uint32 bounds = getNumChildren();
+ for(idx = 1; idx < bounds; ++idx)
+ {
+ const ossimPlanetPagedLandLod* lod = dynamic_cast<const ossimPlanetPagedLandLod*>(getChild(idx));
+ if(lod)
+ {
+ if(!lod->getCulledFlag()) return false;
+ }
+ }
+
+ return true;
+}
+
+bool ossimPlanetPagedLandLod::addChild( Node *child )
+{
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ if(!child) return false;
+
+ ossimPlanetPagedLandLod* lod = dynamic_cast<ossimPlanetPagedLandLod*>(child);
+ ossimPlanetLandTextureRequest *request = dynamic_cast<ossimPlanetLandTextureRequest*>(child);
+ bool result = false;
+ if(lod)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePagedLodListMutex);
+ if(getNumChildren() >4)
+ {
+ return false;
+ }
+
+ if(thePagedLodList.size() < 4)
+ {
+
+ if(lod->theRequestNameList[0] != theRequestNameList[thePagedLodList.size()+1])
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ ossim_uint32 idx = thePagedLodList.size();
+ thePagedLodList.push_back(lod);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockChildList(theChildCullNodeListMutex);
+ theChildCullNodeList[idx] = new ossimPlanetPagedLandLodCullNode(*lod->theCullNode);
+ ossimPlanetLand* land = landLayer();
+ if(land)
+ {
+ land->pagedLodAdded(this, theChildCullNodeList[idx].get());
+ }
+ return true;
+ }
+ else if(request)
+ {
+ if((request->getLevel() == theLevel)&&
+ (request->getRow() == theRow)&&
+ (request->getCol() == theCol))
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTextureRequestMutex);
+ theTextureRequest = request;
+ ossimPlanetLand* land = landLayer();
+ if(land)
+ {
+ land->pagedLodModified(this);
+ }
+
+ return true;
+ }
+ return false;
+ }
+ result = Group::addChild(child);
+
+ return result;
+}
+
+void ossimPlanetPagedLandLod::traverse(osg::NodeVisitor& nv)
+{
+ switch(nv.getTraversalMode())
+ {
+ case osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN:
+ {
+ if(isLeaf())
+ {
+ if(getChild(0))
+ {
+ getChild(0)->accept(nv);
+ }
+ }
+ else
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 1; idx < getNumChildren(); ++idx)
+ {
+ getChild(idx)->accept(nv);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ Group::traverse(nv);
+ break;
+ }
+ }
+}
+
+void ossimPlanetPagedLandLod::setRefreshType(ossimPlanetLandRefreshType refreshType)
+{
+ theRefreshType = refreshType;
+ if(theRefreshType != ossimPlanetLandRefreshType_NONE)
+ {
+ if(landLayer()) landLayer()->setRedrawFlag(true);
+ theTextureRequest = 0;
+ }
+}
+
+ossimPlanetLandRefreshType ossimPlanetPagedLandLod::refreshType()const
+{
+ return theRefreshType;
+}
+
+
+
+ossimPlanetLand* ossimPlanetPagedLandLod::landLayer()
+{
+ osg::Node* parentNode = this;
+ while(parentNode->getNumParents())
+ {
+ parentNode = parentNode->getParent(0);
+ ossimPlanetLand* landPtr = dynamic_cast<ossimPlanetLand*>(parentNode);
+ if(landPtr)
+ {
+ return landPtr;
+ }
+ }
+
+ return 0;
+}
+
+const ossimPlanetLand* ossimPlanetPagedLandLod::landLayer()const
+{
+ const osg::Node* parentNode = this;
+ while(parentNode->getNumParents())
+ {
+ parentNode = parentNode->getParent(0);
+ const ossimPlanetLand* landPtr = dynamic_cast<const ossimPlanetLand*>(parentNode);
+ if(landPtr)
+ {
+ return landPtr;
+ }
+ }while(parentNode);
+
+ return 0;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetPlaneGrid.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetPlaneGrid.cpp
new file mode 100644
index 0000000..a27aabf
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetPlaneGrid.cpp
@@ -0,0 +1,73 @@
+#include <ossimPlanet/ossimPlanetPlaneGrid.h>
+#include <ossim/base/ossimCommon.h>
+
+ossim_uint32 ossimPlanetPlaneGrid::getNumberOfFaces()const
+{
+ return 2;// east and west hemispheres
+}
+
+void ossimPlanetPlaneGrid::getPixelScale(double& dx,
+ double& dy,
+ ossimUnitType& pixelScaleUnits,
+ ossim_uint32 level,
+ ossim_uint64 /*row*/,
+ ossim_uint64 /*col*/)const
+{
+ dx = 180.0*(1.0/(1<<level));
+ dy = dx;
+ dx/=theTileWidth;
+ dy/=theTileHeight;
+ pixelScaleUnits = OSSIM_DEGREES;
+}
+
+void ossimPlanetPlaneGrid::getGridPoint(ossimPlanetGridUtility::GridPoint& gridPoint,
+ const osg::Vec3d& latLon)const
+{
+ osg::Vec2d ll((ossim::clamp((double)latLon[ossimPlanetGridUtility::LAT],
+ (double)-90.0, (double)90.0)+90)/180,
+ (ossim::wrap((double)latLon[ossimPlanetGridUtility::LON],
+ (double)-180.0, (double)180.0)+180)/360);
+
+ gridPoint.theFace = ll[ossimPlanetGridUtility::LON] < 0.0?0:1;
+
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = ll[ossimPlanetGridUtility::LAT];
+ if(gridPoint.theFace == 0)
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = ll[ossimPlanetGridUtility::LON]/.5;
+ }
+ else
+ {
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = (ll[ossimPlanetGridUtility::LON]-.5)/.5;
+ }
+
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX] = ossim::clamp(gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDX],
+ 0.0, 1.0);
+ gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY] = ossim::clamp(gridPoint.theGlobalGridPoint[ossimPlanetGridUtility::GRIDY],
+ 0.0, 1.0);
+}
+
+
+void ossimPlanetPlaneGrid::getLatLon(osg::Vec3d& latLon,
+ const ossimPlanetGridUtility::GridPoint& gridPoint)const
+{
+ latLon[2] = 0.0;
+ switch(gridPoint.theFace)
+ {
+ case 0: // east hemisphere
+ {
+ latLon[0] = 90.0 - (180.0)*gridPoint.theGlobalGridPoint[1];
+ latLon[1] = gridPoint.theGlobalGridPoint[0]*180.0 - 180.0;
+ break;
+ }
+ case 1: // west hemisphere
+ {
+ latLon[0] = 90.0 - (180.0)*gridPoint.theGlobalGridPoint[1];
+ latLon[1] = gridPoint.theGlobalGridPoint[0]*180.0;
+ break;
+ }
+ }
+}
+
+
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetPointModel.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetPointModel.cpp
new file mode 100644
index 0000000..9dfb472
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetPointModel.cpp
@@ -0,0 +1,115 @@
+#include <ossimPlanet/ossimPlanetPointModel.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/mkUtils.h>
+#include <OpenThreads/ScopedLock>
+#include <ossim/base/ossimNotify.h>
+#include <osg/io_utils>
+
+ossimPlanetPointModel::ossimPlanetPointModel()
+:theNodeChangedFlag(false)
+{
+ theLsrSpaceCallback = new LsrSpaceCallback(this);
+ theLsrSpaceTransform = new ossimPlanetLsrSpaceTransform();
+ theLsrSpaceTransform->addCallback(theLsrSpaceCallback.get());
+ theLsrSpaceTransform->setUpdateCallback(new ossimPlanetTraverseCallback());
+}
+
+ossimPlanetPointModel::~ossimPlanetPointModel()
+{
+ if(theLsrSpaceTransform.valid())
+ {
+ theLsrSpaceTransform->removeCallback(theLsrSpaceCallback.get());
+ }
+}
+
+void ossimPlanetPointModel::traverse(osg::NodeVisitor& nv)
+{
+ if(!enableFlag()||!theNode.valid())
+ {
+ ossimPlanetAnnotationLayerNode::traverse(nv);
+ return;
+ }
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ setRedrawFlag(false); // let's reset the redraw notification
+ if(!theLsrSpaceTransform->model()&&layer()) theLsrSpaceTransform->setModel(layer()->model());
+
+ // if(checkPointers())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePointModelPropertyMutex);
+ if(theNodeChangedFlag)
+ {
+ if(theLsrSpaceTransform->getNumChildren() > 0)
+ {
+ theLsrSpaceTransform->removeChildren(0, theLsrSpaceTransform->getNumChildren());
+ }
+ theLsrSpaceTransform->addChild(theNode.get());
+ theNodeChangedFlag = false;
+ }
+ }
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ theLsrSpaceTransform->accept(nv);
+ ossimPlanetAnnotationLayerNode::traverse(nv);
+}
+
+void ossimPlanetPointModel::setNode(osg::Node* node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePointModelPropertyMutex);
+ setRedrawFlag(true);
+
+ theNode = node;
+ theNodeChangedFlag = true;
+}
+
+void ossimPlanetPointModel::copyLsrSpaceParameters(const ossimPlanetLsrSpaceTransform& lsr)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePointModelPropertyMutex);
+ // only need the martrix of the lsr space and all other parameters wil be derived from it.
+ theLsrSpaceTransform->copyParametersOnly(lsr);
+ setRedrawFlag(true);
+}
+
+void ossimPlanetPointModel::setLayer(ossimPlanetLayer* layer)
+{
+ ossimPlanetAnnotationLayerNode::setLayer(layer);
+ if(layer)
+ {
+ theLsrSpaceTransform->setModel(layer->model());
+ setRedrawFlag(true);
+ }
+}
+
+bool ossimPlanetPointModel::checkPointers()
+{
+ if(layer())
+ {
+ if(layer()->model())
+ {
+ return true;
+ }
+ else
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetPointModel::checkPointers() ERROR: model is not found. Try added the annotation layer to planet and add the PointModelNode to the annotation layer";
+ }
+ }
+ else
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetPointModel::checkPointers() ERROR: parent layer is not found.";
+ }
+
+ return false;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetPredatorVideoLayerNode.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetPredatorVideoLayerNode.cpp
new file mode 100644
index 0000000..fe44211
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetPredatorVideoLayerNode.cpp
@@ -0,0 +1,936 @@
+#include <ossimPlanet/ossimPlanetPredatorVideoLayerNode.h>
+#include <iostream>
+#include <osgUtil/CullVisitor>
+#include <osgGA/EventVisitor>
+#include <osgGA/GUIActionAdapter>
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetVideoLayer.h>
+#include <ossim/base/ossimMatrix4x4.h>
+#include <ossim/base/ossimLsrSpace.h>
+#include <sstream>
+#include <ossim/base/ossimDate.h>
+#include <ossim/elevation/ossimElevManager.h>
+
+class ossimPlanetPredatorVideoLayerNodeTraverseCallback : public osg::NodeCallback
+{
+public:
+ ossimPlanetPredatorVideoLayerNodeTraverseCallback()
+ {
+ }
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ if(node)
+ {
+ node->traverse(*nv);
+ }
+ }
+};
+
+ossimPlanetFFMpegImageStream::ossimPlanetFFMpegImageStream()
+ :theBlock(new ossimPlanetRefBlock),
+ theFrameRate(0.0),
+ theSecondsToUpdate(0.0),
+ theEnableFlag(true)
+{
+ _status = osg::ImageStream::PAUSED;
+ _loopingMode = LOOPING;
+}
+
+ossimPlanetFFMpegImageStream::~ossimPlanetFFMpegImageStream()
+{
+}
+
+void ossimPlanetFFMpegImageStream::setVideo(ossimRefPtr<ossimPredatorVideo> video)
+{
+ if(isRunning())
+ {
+ cancel();
+ }
+ theVideo = video;
+ if(theVideo.valid())
+ {
+ theFrameRate = theVideo->videoFrameRate();
+ theSecondsToUpdate = 1.0/theFrameRate;
+ allocateImage(theVideo->imageWidth(),
+ theVideo->imageHeight(),
+ 1,
+ GL_RGB,
+ GL_UNSIGNED_BYTE);
+ memset(data(),
+ 0,
+ theVideo->imageWidth()*
+ theVideo->imageHeight()*3);
+ dirty();
+ theDoneFlag = false;
+ pause();
+ theVideo->setFirstFrameFlag(false);
+ }
+}
+
+int ossimPlanetFFMpegImageStream::cancel()
+{
+ int result = 0;
+
+ if( isRunning() )
+ {
+ theDoneFlag = true;
+ // release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation.
+ theBlock->release();
+
+ // then wait for the the thread to stop running.
+ while(isRunning())
+ {
+ OpenThreads::Thread::YieldCurrentThread();
+ }
+ }
+
+ return result;
+}
+void ossimPlanetFFMpegImageStream::CoordinateInfo::setDescriptionToKlvMetadata()
+{
+ if(!theKlvTable.valid()) return;
+ ossimString value;
+ theDescription = "";
+ if(theKlvTable->valueAsString(value, KLV_KEY_ORGANIZATIONAL_PROGRAM_NUMBER))
+ {
+ theDescription += ("Orgnizational Program Number: " + value + "<br>");
+ }
+ ossimDate date;
+ if(theKlvTable->getDate(date, false))
+ {
+ std::stringstream temp;
+ temp << std::setw(4) << date.getYear() <<"-"
+ << std::setw(2) << std::setfill('0') << date.getMonth() << "-"
+ << std::setw(2) << std::setfill('0') << date.getDay() << " "
+ << std::setw(2) << std::setfill('0') << date.getHour() << ":"
+ << std::setw(2) << std::setfill('0') << date.getMin() << ":"
+ << std::setw(2) << std::setfill('0') << date.getSec() << "<br>";
+ theDescription += ("Date: " + temp.str());
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_MISSION_NUMBER))
+ {
+ theDescription += "Mission ID: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SECURITY_CLASSIFICATION_SET))
+ {
+ theDescription += "Security Classification: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CLASSIFICATION_COMMENT))
+ {
+ theDescription += "Classification Comment: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SECURITY_CAVEATS))
+ {
+ theDescription += "Security Caveats: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_ORIGINAL_PRODUCER_NAME))
+ {
+ theDescription += "Original Producer Name: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_PLATFORM_HEADING_ANGLE))
+ {
+ theDescription += "Platform Heading: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_PLATFORM_PITCH_ANGLE))
+ {
+ theDescription += "Platform Pitch: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_PLATFORM_ROLL_ANGLE))
+ {
+ theDescription += "Platform Roll: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_PLATFORM_DESIGNATION))
+ {
+ theDescription += "Designation: " + value + "<br>";
+ }
+ else if(theKlvTable->valueAsString(value, KLV_KEY_PLATFORM_DESIGNATION2))
+ {
+ theDescription += "Designation: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_IMAGE_SOURCE_SENSOR))
+ {
+ theDescription += "Image Source Sensor: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_IMAGE_COORDINATE_SYSTEM))
+ {
+ theDescription += "Coordinate System: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SENSOR_LATITUDE))
+ {
+ theDescription += "Sensor Latitude: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SENSOR_LONGITUDE))
+ {
+ theDescription += "Sensor Longitude: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SENSOR_TRUE_ALTITUDE))
+ {
+ theDescription += "Sensor Altitude: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SENSOR_HORIZONTAL_FOV))
+ {
+ theDescription += "Horizontal Field Of View: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SENSOR_VERTICAL_FOV1))
+ {
+ theDescription += "Vertical Field Of View: " + value + "<br>";
+ }
+ else if(theKlvTable->valueAsString(value, KLV_KEY_SENSOR_VERTICAL_FOV2))
+ {
+ theDescription += "Vertical Field Of View: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_SLANT_RANGE))
+ {
+ theDescription += "Slant Range: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_OBLIQUITY_ANGLE))
+ {
+ theDescription += "Obliquity Angle: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_ANGLE_TO_NORTH))
+ {
+ theDescription += "Angle To North: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_TARGET_WIDTH))
+ {
+ theDescription += "Target Width: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_FRAME_CENTER_LATITUDE))
+ {
+ theDescription += "Frame Center Latitude: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_FRAME_CENTER_LONGITUDE))
+ {
+ theDescription += "Frame Center Longitude: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_FRAME_CENTER_ELEVATION))
+ {
+ theDescription += "Frame Center Elevation: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LATITUDE_POINT_1))
+ {
+ theDescription += "Corner Latitude 1: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LONGITUDE_POINT_1))
+ {
+ theDescription += "Corner Longitude 1: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LATITUDE_POINT_2))
+ {
+ theDescription += "Corner Latitude 2: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LONGITUDE_POINT_2))
+ {
+ theDescription += "Corner Longitude 2: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LATITUDE_POINT_3))
+ {
+ theDescription += "Corner Latitude 3: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LONGITUDE_POINT_3))
+ {
+ theDescription += "Corner Longitude 3: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LATITUDE_POINT_4))
+ {
+ theDescription += "Corner Latitude 4: " + value + "<br>";
+ }
+ if(theKlvTable->valueAsString(value, KLV_KEY_CORNER_LONGITUDE_POINT_4))
+ {
+ theDescription += "Corner Longitude 4: " + value + "<br>";
+ }
+
+}
+
+void ossimPlanetFFMpegImageStream::run()
+{
+ if(!theVideo.valid()) return;
+
+ while(!theDoneFlag)
+ {
+ theBlock->block();
+ if(theDoneFlag) return;
+ ossimRefPtr<ossimPredatorVideo::FrameInfo> frame = theVideo->nextFrame();
+ osg::Timer_t lastFrameTick;
+ lastFrameTick = osg::Timer::instance()->tick();
+ if(frame.valid())
+ {
+ memcpy(data(),
+ frame->rgbBuffer(),
+ frame->rgbBufferSizeInBytes());
+ dirty();
+ ossimRefPtr<ossimPredatorKlvTable> klvTable = frame->klvTable();
+ if(klvTable.valid())
+ {
+// ossimPlanetFFMpegImageStream::CoordinateInfo coord;
+ ossim_float64 lat=0.0, lon=0.0, elev=0.0;
+ ossim_float64 flat=0.0, flon=0.0, felev=0.0;
+// ossim_float32 h=0.0, p=0.0, r=0.0;
+ ossim_float32 obliquityAngle=0.0;
+// ossim_float32 slantRange=0.0;
+// ossim_float32 hfov=0.0;
+// ossim_float32 vfov=0.0;
+ ossim_float32 targetWidthInMeters=1.0;
+ ossim_float32 angleToNorth=0.0;
+// ossim_float32 roll=0.0;
+
+ // if we at least have a frame center and a target width let's go on that
+
+ if(klvTable->getTargetWidthInMeters(targetWidthInMeters)&&
+ klvTable->getFrameCenter(flat, flon, felev))
+ {
+ osg::ref_ptr<CoordinateInfo> coordInfo = new CoordinateInfo;
+ coordInfo->theKlvTable = klvTable->dup();
+ coordInfo->theReferenceTime = theVideo->referenceTime();
+ coordInfo->theClock = theVideo->videoClock();
+ ossim_float32 slantRange=0.0;
+ ossimGpt pt1, pt2, pt3, pt4;
+
+ if(theModel.valid())
+ {
+ felev = theModel->getHeightAboveEllipsoid(flat, flon);
+ }
+ else
+ {
+ // this is a hack for now until I fix the model synching problem.
+ //
+ felev = ossimElevManager::instance()->getHeightAboveEllipsoid(ossimGpt(flat, flon));
+ if(ossim::isnan(felev))
+ {
+ felev = 0;
+ }
+ }
+ coordInfo->theFrameCenterLlhValidFlag = true;
+ coordInfo->theFrameCenterLlh = osg::Vec3d(flat, flon, felev);
+ coordInfo->theTargetWidthInMetersValidFlag = true;
+ coordInfo->theTargetWidthInMeters = targetWidthInMeters;
+ if(klvTable->getCornerPoints(pt1, pt2, pt3, pt4))
+ {
+ coordInfo->theCornerPoints.resize(4);
+ coordInfo->theCornerPoints[0] = osg::Vec3d(pt1.latd(), pt1.lond(), pt1.height());
+ coordInfo->theCornerPoints[1] = osg::Vec3d(pt2.latd(), pt2.lond(), pt2.height());
+ coordInfo->theCornerPoints[2] = osg::Vec3d(pt3.latd(), pt3.lond(), pt3.height());
+ coordInfo->theCornerPoints[3] = osg::Vec3d(pt4.latd(), pt4.lond(), pt4.height());
+ }
+ else
+ {
+ coordInfo->theCornerPoints.clear();
+ }
+ // now let's see if we can have full orientation. This will be the best we can do fr now.
+ // The meta data doesn't seem to fit line of site. So, we will get what we can and then rotate that
+ // into the platform center to frame center vector so at least the center pixel projects to the meta
+ // data frame center.
+ //
+ if(klvTable->getSlantRange(slantRange))
+ {
+ coordInfo->theSlantRange = slantRange;
+ }
+ else
+ {
+ coordInfo->theSlantRangeValidFlag = false;
+ }
+ if(klvTable->getAngleToNorth(angleToNorth)&&
+ klvTable->getObliquityAngle(obliquityAngle)&&
+ klvTable->getSensorPosition(lat, lon, elev))
+ {
+ if(ossim::almostEqual(elev, 0.0)&&theModel.valid())
+ {
+ elev = theModel->getHeightAboveEllipsoid(lat, lon);
+ }
+ else if(theModel.valid())
+ {
+ elev += theModel->getGeoidOffset(lat, lon);
+ }
+
+ ossimGpt sensorGpt(lat, lon, elev);
+ ossimGpt frameGpt(flat, flon, felev);
+ osg::Matrixd orientationMatrix;
+
+ ossimLsrSpace lsrSpace(sensorGpt,
+ angleToNorth);
+ ossimMatrix4x4 lsrMatrix(lsrSpace.lsrToEcefRotMatrix());
+ NEWMAT::Matrix orientation = (ossimMatrix4x4::createRotationXMatrix(obliquityAngle,
+ OSSIM_LEFT_HANDED));
+ ossimEcefPoint sensorEcefPosition = sensorGpt;
+ ossimEcefPoint frameCenterEcefPosition = frameGpt;
+ ossimEcefVector zAxis = sensorEcefPosition - frameCenterEcefPosition;
+ ossimEcefVector yCol(orientation[0][1],
+ orientation[1][1],
+ orientation[2][1]);
+ ossimEcefVector xAxis = yCol.cross(zAxis);
+ ossimEcefVector yAxis = zAxis.cross(xAxis);
+ xAxis.normalize();
+ yAxis.normalize();
+
+ coordInfo->theOrientationMatrix(0, 0) = xAxis.x();
+ coordInfo->theOrientationMatrix(0, 1) = xAxis.y();
+ coordInfo->theOrientationMatrix(0, 2) = xAxis.z();
+ coordInfo->theOrientationMatrix(1, 0) = yAxis.x();
+ coordInfo->theOrientationMatrix(1, 1) = yAxis.y();
+ coordInfo->theOrientationMatrix(1, 2) = yAxis.z();
+ coordInfo->theOrientationMatrix(2, 0) = zAxis.x();
+ coordInfo->theOrientationMatrix(2, 1) = zAxis.y();
+ coordInfo->theOrientationMatrix(2, 2) = zAxis.z();
+
+ coordInfo->theSensorPositionLlh[0] = lat;
+ coordInfo->theSensorPositionLlh[1] = lon;
+ coordInfo->theSensorPositionLlh[2] = elev;
+
+ }
+ else
+ {
+ coordInfo->theOrientationMatrixValidFlag = false;
+ }
+ coordInfo->setDescriptionToKlvMetadata();
+ if(theCallback.valid())
+ {
+ theCallback->coordinatesChanged(klvTable,
+ coordInfo);
+ }
+ }
+ }
+ }
+ if(!frame.valid())
+ {
+ if(_loopingMode == NO_LOOPING)
+ {
+ theDoneFlag = true;
+ }
+ else
+ {
+// theMutex.lock();
+ rewind();
+ if(theCallback.valid())
+ {
+ theCallback->referenceTimeChanged(0.0);
+ }
+// theMutex.unlock();
+ }
+ }
+ else if(theCallback.valid())
+ {
+// std::cout << "TIME CHANGE = " << getReferenceTime() << "\n";
+ theCallback->referenceTimeChanged(getReferenceTime());
+ }
+ // now delay based on frame rate
+ // we later need to add support for slow play and fast play and
+ // seeking. For now we do constant source frame rate
+ //
+ double delta = osg::Timer::instance()->delta_s(lastFrameTick, osg::Timer::instance()->tick());
+ if((delta < theSecondsToUpdate)&&
+ (delta >= 0.0))
+ {
+ //double idolTime = theSecondsToUpdate-delta;
+ OpenThreads::Thread::microSleep(theSecondsToUpdate*1e6);
+ }
+
+ updateThreadBlock();
+ }
+}
+
+void ossimPlanetFFMpegImageStream::play()
+{
+ _status = osg::ImageStream::PLAYING;
+ if (!isRunning())
+ {
+ if(theVideo.valid())
+ {
+ theDoneFlag = false;
+ theVideo->setFirstFrameFlag(false);
+ updateThreadBlock();
+ start();
+ }
+ }
+ updateThreadBlock();
+}
+
+void ossimPlanetFFMpegImageStream::pause()
+{
+ _status = ImageStream::PAUSED;
+ updateThreadBlock();
+}
+
+void ossimPlanetFFMpegImageStream::rewind()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ theVideo->setFirstFrameFlag(false);
+ theVideo->seek(0.0, ossimPredatorVideo::SEEK_ABSOLUTE);
+ updateThreadBlock();
+}
+
+void ossimPlanetFFMpegImageStream::quit(bool waitForThreadToExit)
+{
+ theDoneFlag = true;
+ if(waitForThreadToExit)
+ {
+ cancel();
+ }
+ else
+ {
+ // make sure we are not blocked
+ theBlock->release();
+ }
+}
+
+double ossimPlanetFFMpegImageStream::getLength() const
+{
+ return theVideo.valid()?theVideo->duration():0.0;
+}
+
+void ossimPlanetFFMpegImageStream::setReferenceTime(double t)
+{
+ // need to add the seeking based on time offset
+ //
+ if(theVideo.valid())
+ {
+ theVideo->seek(t, ossimPredatorVideo::SEEK_ABSOLUTE);
+ updateThreadBlock();
+ }
+}
+
+double ossimPlanetFFMpegImageStream::getReferenceTime()
+{
+ if(theVideo.valid())
+ {
+ return theVideo->referenceTime();
+ }
+ return 0.0;
+}
+
+void ossimPlanetFFMpegImageStream::setTimeMultiplier(double)
+{
+}
+
+double ossimPlanetFFMpegImageStream::getTimeMultiplier()
+{
+ return 0.0;
+}
+
+void ossimPlanetFFMpegImageStream::setVolume(float)
+{
+}
+
+float ossimPlanetFFMpegImageStream::getVolume()
+{
+ return 0.0;
+}
+
+ossimPlanetPredatorVideoLayerNode::ossimPlanetPredatorVideoLayerNode(ossimPlanetVideoLayer* layer)
+ :ossimPlanetVideoLayerNode(layer)
+{
+
+ theAspect = 1.0;
+ theInvAspect = 1.0;
+ theGeometryFlag = false;
+ theCurrentFrame = new ossimPlanetFFMpegImageStream;
+ theCallback = new ossimPlanetPredatorVideoLayerNode::ImageStreamCallback(this);
+ theCurrentFrame->setCallback(theCallback.get());
+ setUpdateCallback(new ossimPlanetPredatorVideoLayerNodeTraverseCallback);
+ setEventCallback(new ossimPlanetPredatorVideoLayerNodeTraverseCallback);
+ setCullCallback(new ossimPlanetPredatorVideoLayerNodeTraverseCallback);
+ theCameraNode = new osg::CameraNode;
+ theSwitchNode = new osg::Switch;
+ theIcon = new ossimPlanetIconGeom;
+ theCameraNode = new osg::CameraNode;
+ theSharedGeode = new osg::Geode;
+ theCullFlag = false;
+ // theIcon->setGeometry(osg::Vec3d(0.0,0.0,0.0),
+// osg::Vec3d(0.0, 0.0, 0.0),
+// osg::Vec3d(0.0, 0.0, 0.0));
+ theSharedGeode->addDrawable(theIcon.get());
+
+// theGroup = new osg::Group;
+ theCameraNode->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ theCameraNode->setViewMatrix(osg::Matrix::identity());
+ theCameraNode->setClearMask(GL_DEPTH_BUFFER_BIT);
+ theCameraNode->setRenderOrder(osg::CameraNode::POST_RENDER);
+ osg::StateSet* stateset = theCameraNode->getOrCreateStateSet();
+ stateset->setMode(GL_LIGHTING,
+ osg::StateAttribute::OFF);
+// stateset->setMode(GL_COLOR_MATERIAL,
+// osg::StateAttribute::OFF);
+ stateset->setMode(GL_DEPTH_TEST,
+ osg::StateAttribute::OFF);
+ stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+ stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ theCameraNode->setStateSet(stateset);
+// addChild(theCameraNode.get());
+ the2DMatrixTransform = new osg::MatrixTransform;
+ the2DMatrixTransform->addChild(theSharedGeode.get());
+ theCameraNode->addChild(the2DMatrixTransform.get());
+
+
+ // SETUP for billboard option
+ //
+ theBillboard = new ossimPlanetBillboardIcon;
+ theBillboardMatrixTransform = new osg::MatrixTransform;
+ theBillboardMatrixTransform->addChild(theBillboard.get());
+ stateset = theBillboard->getOrCreateStateSet();
+ stateset->setMode(GL_LIGHTING,
+ osg::StateAttribute::OFF);
+// stateset->setMode(GL_COLOR_MATERIAL,
+// osg::StateAttribute::OFF);
+ stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
+// stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ theBillboard->setStateSet(stateset);
+ theSwitchNode->addChild(theCameraNode.get());
+ theSwitchNode->addChild(theBillboardMatrixTransform.get());
+
+ addChild(theSwitchNode.get());
+// setRenderMode(ossimPlanetVideoLayerNode::RENDER_SCREEN);
+ setRenderMode(ossimPlanetVideoLayerNode::RENDER_BILLBOARD);
+
+}
+
+ossimPlanetPredatorVideoLayerNode::~ossimPlanetPredatorVideoLayerNode()
+{
+
+ theCurrentFrame->setCallback(0);
+ theCurrentFrame->cancel();
+}
+
+bool ossimPlanetPredatorVideoLayerNode::open(const ossimFilename& file)
+{
+ ossimRefPtr<ossimPredatorVideo> video = new ossimPredatorVideo;
+
+ bool result = video->open(file);
+ if(!result)
+ {
+ video = 0;
+ }
+ else
+ {
+ setName(file.file().c_str());
+ }
+ setVideo(video.get());
+ return result;
+}
+
+void ossimPlanetPredatorVideoLayerNode::setVideo(ossimPredatorVideo* video)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePredatorTraverseMutex);
+ theCurrentFrame->cancel();
+
+ theGeometryFlag = false;
+ theVideo = video;
+ theLookAt = 0;
+ if(theVideo.valid())
+ {
+ theFrameRate = theVideo->videoFrameRate();
+ theSecondsToUpdate = 1.0/theFrameRate;
+ theCurrentFrame->setVideo(video);
+ theIcon->setTexture(theCurrentFrame.get());
+ osg::ref_ptr<osg::Vec3Array> coords = dynamic_cast<osg::Vec3Array*>(theIcon->getVertexArray());
+
+ the2DMatrixTransform->setMatrix(osg::Matrixd::scale(osg::Vec3d(theVideo->imageWidth(),
+ theVideo->imageHeight(),
+ 1.0))*
+ osg::Matrixd::translate(osg::Vec3d(theVideo->imageWidth()*.5,
+ theVideo->imageHeight()*.5,
+ 0.0)));
+ theAspect = (ossim_float64)theVideo->imageWidth()/(ossim_float64)theVideo->imageHeight();
+ theInvAspect = 1.0/theAspect;
+ theSharedTexture = new osg::Texture2D;
+ theSharedTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture2D::LINEAR);
+ theSharedTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture2D::LINEAR);
+ theSharedTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
+ theSharedTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
+ theSharedTexture->setWrap(osg::Texture2D::WRAP_R, osg::Texture2D::CLAMP_TO_EDGE);
+ theSharedTexture->setDataVariance(osg::Object::DYNAMIC);
+ theSharedTexture->setResizeNonPowerOfTwoHint(false);
+ theSharedTexture->setImage(theCurrentFrame.get());
+ theIcon->setTexture(theSharedTexture.get());
+ theViewportChangedFlag = false;
+
+ // set anything needed for the billboard on initialization
+ theBillboard->setGeom(theIcon.get());
+ theBillboard->setMinPixelSize(64);
+
+ setRedrawFlag(true);
+ theCurrentFrame->updateThreadBlock();
+ theCurrentFrame->start();
+ // force a reset on any icon geometries
+ setRenderMode(renderMode());
+ }
+}
+
+void ossimPlanetPredatorVideoLayerNode::pause()
+{
+ theCurrentFrame->pause();
+ setRedrawFlag(true);
+
+}
+
+void ossimPlanetPredatorVideoLayerNode::rewind()
+{
+ theCurrentFrame->rewind();
+ setRedrawFlag(true);
+}
+
+void ossimPlanetPredatorVideoLayerNode::play()
+{
+ theCurrentFrame->play();
+ setRedrawFlag(true);
+}
+
+
+ossimPlanetVideoLayerNode::Status ossimPlanetPredatorVideoLayerNode::status()const
+{
+ switch(theCurrentFrame->getStatus())
+ {
+ case osg::ImageStream::PLAYING:
+ {
+ return ossimPlanetVideoLayerNode::STATUS_PLAYING;
+ }
+ case osg::ImageStream::PAUSED:
+ {
+ return ossimPlanetVideoLayerNode::STATUS_PAUSED;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return ossimPlanetVideoLayerNode::STATUS_NONE;
+}
+
+
+ossim_float64 ossimPlanetPredatorVideoLayerNode::duration()const
+{
+ return (ossim_float64)theCurrentFrame->getLength();
+}
+
+void ossimPlanetPredatorVideoLayerNode::setReferenceTime(ossim_float64 referenceTime)
+{
+ theCurrentFrame->setReferenceTime(referenceTime);
+ setRedrawFlag(true);
+}
+
+ossim_float64 ossimPlanetPredatorVideoLayerNode::referenceTime()const
+{
+ return theCurrentFrame->getReferenceTime();
+}
+
+void ossimPlanetPredatorVideoLayerNode::setRenderMode(ossimPlanetVideoLayerNode::RenderMode mode)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePredatorTraverseMutex);
+ if(mode == ossimPlanetVideoLayerNode::RENDER_OVERLAY)
+ {
+ std::cout << "ossimPlanetPredatorVideoLayerNode::setRenderMode: OVERLAY REDNERING NOT SUPPORTED YET!" << std::endl;
+ std::cout << "ossimPlanetPredatorVideoLayerNode::setRenderMode: DEFAULTING TO SCREEN MODE!" << std::endl;
+ mode = ossimPlanetVideoLayerNode::RENDER_SCREEN;
+ }
+ ossimPlanetVideoLayerNode::setRenderMode(mode);
+ switch(mode)
+ {
+ case ossimPlanetVideoLayerNode::RENDER_SCREEN:
+ {
+ theIcon->setGeometry(osg::Vec3d(-.5, .5, 0.0),
+ osg::Vec3d(1.0, 0.0, 0.0),
+ osg::Vec3d(0.0, -1.0, 0.0));
+ break;
+ }
+ case ossimPlanetVideoLayerNode::RENDER_BILLBOARD:
+ {
+ // change the geometry based on the render mode;
+ theIcon->setGeometry(osg::Vec3d(-.5*theAspect, 0.0, .5),
+ osg::Vec3d(theAspect, 0.0, 0.0),
+ osg::Vec3d(0.0, 0.0, -1.0));
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ theSwitchNode->setSingleChildOn((int)mode);
+}
+
+void ossimPlanetPredatorVideoLayerNode::traverse(osg::NodeVisitor& nv)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePredatorTraverseMutex);
+ bool traverseChildrenFlag = !theCullFlag&&theEnableFlag;
+
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ ossimPlanet* planet = videoLayer()->planet();
+ osg::ref_ptr<ossimPlanetGeoRefModel> model = planet->model();
+ if(theCurrentFrame.valid())
+ {
+ if(!theCurrentFrame->model().valid())
+ {
+ theCurrentFrame->setModel(model.get());
+ }
+ }
+ if(!theEnableFlag)
+ {
+ break;
+ }
+ //bool needNewCoordinates = false;
+ osg::ref_ptr<ossimPlanetFFMpegImageStream::CoordinateInfo> coordInfo;
+ theCoordinateMutex.lock();
+ if(theCoordinates.valid())
+ {
+ coordInfo = theCoordinates->dup();
+ theCoordinates = 0;
+ }
+// needNewCoordinates = theCoordinatesChangedFlag;
+// theCoordinatesChangedFlag = false;
+ if(!theGeometryFlag)
+ {
+ osg::Matrixd localToWorld;
+ theBillboard->setGroundObjectSize(5000*
+ planet->model()->getInvNormalizationScale());
+
+ model->lsrMatrix(osg::Vec3d(0, 0, 0),
+ localToWorld);
+ theBillboardMatrixTransform->setMatrix(localToWorld);
+ theGeometryFlag = true;
+ theCullDistance = 10000*planet->model()->getInvNormalizationScale();
+ model->forward(osg::Vec3d(0.0,0.0,0.0), theFrameCenter);
+ }
+ theCoordinateMutex.unlock();
+ if(coordInfo.valid())
+ {
+ if(description()!=coordInfo->theDescription)
+ {
+ setDescription(coordInfo->theDescription);
+ }
+// std::cout << "Updating coordinates!!" << std::endl;
+ if(planet&&
+ coordInfo->theFrameCenterLlhValidFlag&&
+ coordInfo->theOrientationMatrixValidFlag&&
+ coordInfo->theSlantRangeValidFlag)
+ {
+
+ osg::Matrixd localToWorld;
+ ossim_float64 targetInMeters = coordInfo->theTargetWidthInMeters;
+ if(targetInMeters < 1.0)
+ {
+ targetInMeters = 5000;
+ }
+ ossim_float64 cullTarget = (coordInfo->theSlantRange*
+ planet->model()->getInvNormalizationScale());
+ theBillboard->setGroundObjectSize(targetInMeters*
+ planet->model()->getInvNormalizationScale());
+ model->lsrMatrix(coordInfo->theFrameCenterLlh,
+ localToWorld);
+ osg::Vec3d hpr;
+ mkUtils::matrixToHpr(hpr, localToWorld, coordInfo->theOrientationMatrix);
+
+ if(!theLookAt.valid())
+ {
+ theLookAt = new ossimPlanetLookAt;
+ }
+ theLookAt->setAll(coordInfo->theFrameCenterLlh[0], coordInfo->theFrameCenterLlh[1], coordInfo->theFrameCenterLlh[2],
+ hpr[0], hpr[1], hpr[2],
+ coordInfo->theSlantRange,
+ ossimPlanetAltitudeMode_ABSOLUTE);
+ model->forward(coordInfo->theFrameCenterLlh, theFrameCenter);
+ theBillboardMatrixTransform->setMatrix(localToWorld);
+ theCullDistance = cullTarget*5;
+ }
+ }
+ if(theViewport.valid()&&theViewportChangedFlag)
+ {
+ theCameraNode->setProjectionMatrix(osg::Matrix::ortho2D(theViewport->x(),
+ theViewport->width(),
+ theViewport->y(),
+ theViewport->height()));
+ ossim_float64 dx = theViewport->width()*.5;
+ ossim_float64 dy = theViewport->height()*.5;
+ the2DMatrixTransform->setMatrix(osg::Matrixd::scale(osg::Vec3d(theVideo->imageWidth(),
+ theVideo->imageHeight(),
+ 1.0))*
+ osg::Matrixd::translate(osg::Vec3d(theViewport->x() + dx,
+ theViewport->y() + dy,
+ 0.0)));
+ theViewportChangedFlag = false;
+ setRedrawFlag(true);
+ }
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+// if(!theEnableFlag)
+// {
+// break;
+// }
+
+ osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(cullVisitor)
+ {
+ theCullFlag = nv.getDistanceToEyePoint(theFrameCenter, false) > theCullDistance;
+ traverseChildrenFlag = theEnableFlag&&!theCullFlag;
+ if(!theCullFlag)
+ {
+ double x = cullVisitor->getViewport()->x();
+ double y = (int)cullVisitor->getViewport()->y();
+ double w = (int)cullVisitor->getViewport()->width();
+ double h = (int)cullVisitor->getViewport()->height();
+ if(!theViewport.valid())
+ {
+ theViewport = new osg::Viewport(x,y,w,h);
+ theViewportChangedFlag = true;
+ }
+ else
+ {
+ if( !ossim::almostEqual(theViewport->x(), x)||
+ !ossim::almostEqual(theViewport->y(), y)||
+ !ossim::almostEqual(theViewport->width(), w)||
+ !ossim::almostEqual(theViewport->height(), h))
+ {
+ theViewport->setViewport(x,y,w,h);
+ theViewportChangedFlag = true;
+ }
+ }
+ }
+ break;
+ }
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
+ if(ev)
+ {
+ const osgGA::EventVisitor::EventList& eventList = ev->getEvents();
+ osgGA::EventVisitor::EventList::const_iterator iter = eventList.begin();
+ if(eventList.size())
+ {
+ if(((*iter)->getEventType() == osgGA::GUIEventAdapter::FRAME))
+ {
+ if(ev->getActionAdapter())
+ {
+ if(theRedrawFlag)
+ {
+ ev->getActionAdapter()->requestRedraw();
+ theRedrawFlag = false;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ theCurrentFrame->setEnableFlag(traverseChildrenFlag);
+ if(traverseChildrenFlag)
+ {
+ ossimPlanetVideoLayerNode::traverse(nv);
+ }
+}
+
+void ossimPlanetPredatorVideoLayerNode::updateIconGeometry()
+{
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetSceneView.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetSceneView.cpp
new file mode 100644
index 0000000..b78c0cc
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetSceneView.cpp
@@ -0,0 +1,214 @@
+#include <iostream>
+#include <osg/Projection>
+#include <ossimPlanet/ossimPlanetSceneView.h>
+#include <osg/LineSegment>
+#include <ossim/base/ossimConstants.h>
+
+
+ossimPlanetSceneView::ossimPlanetSceneView()
+{
+}
+
+// bool ossimPlanetSceneView::intersectScene(osg::Vec3d& intersection,
+// const osg::Vec3d& startPt,
+// const osg::Vec3d& endPt)
+// {
+// if(!getSceneData()) return false;
+// osg::ref_ptr<osg::LineSegment> segLookVector = new osg::LineSegment;
+
+// osgUtil::IntersectVisitor iv;
+// osg::Vec3d s = startPt;
+// osg::Vec3d e = endPt;
+
+// segLookVector->set(s, e);
+// iv.addLineSegment(segLookVector.get());
+
+// getSceneData()->accept(iv);
+// bool hitFound = false;
+// if (iv.hits())
+// {
+// osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segLookVector.get());
+// if (!hitList.empty())
+// {
+// intersection = hitList.front().getWorldIntersectPoint();
+
+// hitFound = true;
+// }
+// }
+
+// return hitFound;
+// }
+
+bool ossimPlanetSceneView::pickObjects(osgUtil::IntersectVisitor::HitList& hits,
+ osg::Node* startNode,
+ double vx, double vy,
+ double /*startPointShift*/)
+{
+ osg::Node* rootNode = 0;
+ if(startNode)
+ {
+ rootNode = startNode;
+ }
+ else
+ {
+ rootNode = getSceneData();
+ }
+ osg::Matrixd proj = getProjectionMatrix();
+ osg::Matrixd view = getViewMatrix();
+ const osg::Viewport* viewport = getViewport();
+ osg::Matrixd projToWindow = viewport->computeWindowMatrix();
+ osg::Vec3d projPt(vx, vy, 1.0);
+ osg::Vec3d windowPt = projPt*projToWindow;
+
+ osg::NodePathList parentNodePaths = rootNode->getParentalNodePaths(rootNode);
+ for(unsigned int i=0;i<parentNodePaths.size();++i)
+ {
+ osg::NodePath& nodePath = parentNodePaths[i];
+
+ // remove the intersection node from the nodePath as it'll be accounted for
+ // in the PickVisitor traversal, so we don't double account for its transform.
+ if (!nodePath.empty()) nodePath.pop_back();
+
+ osg::Matrixd modelview(view);
+ // modify the view matrix so that it accounts for this nodePath's accumulated transform
+ if (!nodePath.empty()) modelview.preMult(computeLocalToWorld(nodePath));
+
+ osgUtil::PickVisitor pick(viewport, proj, modelview, windowPt[0], windowPt[1]);
+ pick.setTraversalMask(0xffffffff);
+ rootNode->accept(pick);
+
+ // copy all the hits across to the external hits list
+ for(osgUtil::PickVisitor::LineSegmentHitListMap::iterator itr = pick.getSegHitList().begin();
+ itr != pick.getSegHitList().end();
+ ++itr)
+ {
+ hits.insert(hits.end(), itr->second.begin(), itr->second.end());
+ }
+
+ }
+
+ return !hits.empty();
+}
+
+bool ossimPlanetSceneView::intersectScene(osg::Node* startNode,
+ osg::Vec3d& intersectionPoint,
+ double vx, double vy,
+ double startPointShift)
+{
+ osgUtil::IntersectVisitor::HitList hits;
+ if(!pickObjects(hits, startNode, vx, vy, startPointShift))
+ {
+ return false;
+ }
+ intersectionPoint = hits.front().getWorldIntersectPoint();
+
+ return true;
+}
+
+// bool ossimPlanetSceneView::computeNadirIntersection(osg::Vec3d& intersectionPoint,
+// double startPointShift)
+// {
+// osg::Vec3 eye(0,0,0);
+// osg::Vec3 center(0,0,0);
+// osg::Vec3 up(0,0,0);
+// osg::Vec3d start;
+// getViewMatrixAsLookAt(eye, center, up);
+// osg::Vec3d direction = center-eye;
+// direction.normalize();
+// intersectionPoint = osg::Vec3d(0.0,0.0,0.0);
+// start = eye + direction*startPointShift;
+// return intersectScene(intersectionPoint,
+// start,
+// start + direction*(1.0/FLT_EPSILON));
+// }
+
+bool ossimPlanetSceneView::computeLineOfSiteIntersection(osg::Vec3d& intersectionPoint,
+ double startPointShift)
+{
+ osg::Viewport* v = getViewport();
+
+ if(v)
+ {
+ return intersectScene(0,
+ intersectionPoint,
+ (double)v->x() + v->width()/2.0,
+ (double)v->y() + v->height()/2.0,
+ startPointShift);
+ }
+
+ intersectionPoint = osg::Vec3d(0.0,0.0,0.0);
+
+ return false;
+}
+
+// bool ossimPlanetSceneView::makeRay(osg::Vec3d& origin,
+// osg::Vec3d& ray,
+// double vx, double vy)
+// {
+// osg::Vec3 eye(0,0,0);
+// osg::Vec3 center(0,0,0);
+// osg::Vec3 up(0,0,0);
+// osg::Vec3 direction;
+// double fov;
+// double aspectRatio;
+// double znear;
+// double zfar;
+// osg::Matrixd pm = getProjectionMatrix();
+// ray[0] = 0;
+// ray[1] = 0;
+// ray[2] = 0;
+
+// if(!pm.getPerspective(fov, aspectRatio, znear, zfar))
+// {
+// return false;
+// }
+// getViewMatrixAsLookAt(eye, center, up, 1000.0);
+// osg::Matrixd iv = getViewMatrix();
+
+// const osg::ref_ptr<osg::Viewport> viewport = getViewport();
+// osg::Matrix wm;
+// wm.invert(viewport->computeWindowMatrix());
+// osg::Vec3d normalizedPoint = osg::Vec3d(vx,vy,0.0)*wm;
+
+// double angleY = (fov*.5)*normalizedPoint[1];
+// double angleX = (fov*.5)*normalizedPoint[0]*aspectRatio;
+// // double angleX = (fov*.5)*normalizedPoint[0];
+// // double angleY = (fov*.5)*normalizedPoint[1];
+// direction = center - eye;
+// direction.normalize();
+
+// osg::Vec3d crossVec = direction^up;
+// osg::Vec3d newUp = crossVec^direction;
+// osg::Matrixd m = (osg::Matrixd::rotate(-angleX*(M_PI/180.0), newUp)*
+// osg::Matrixd::rotate(angleY*(M_PI/180.0), crossVec));
+// ray = direction*m;
+// origin = eye;
+
+// return true;
+// }
+
+void ossimPlanetSceneView::getEyePosition(osg::Vec3d& eye)const
+{
+ osg::Vec3 eyeTemp(0,0,0);
+ osg::Vec3 center(0,0,0);
+ osg::Vec3 up(0,0,0);
+
+ (const_cast<ossimPlanetSceneView*>(this))->getViewMatrixAsLookAt(eyeTemp, center, up);
+
+ eye[0] = eyeTemp[0];
+ eye[1] = eyeTemp[1];
+ eye[2] = eyeTemp[2];
+}
+
+void ossimPlanetSceneView::getLookDirection(osg::Vec3d& direction)const
+{
+ osg::Vec3 eyeTemp(0,0,0);
+ osg::Vec3 center(0,0,0);
+ osg::Vec3 up(0,0,0);
+
+ (const_cast<ossimPlanetSceneView*>(this))->getViewMatrixAsLookAt(eyeTemp, center, up);
+
+ direction = (center-eyeTemp);
+
+ direction.normalize();
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetServerThread.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetServerThread.cpp
new file mode 100644
index 0000000..4b5a281
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetServerThread.cpp
@@ -0,0 +1,310 @@
+#include <ossimPlanet/ossimPlanetServerThread.h>
+#include <OpenThreads/ScopedLock>
+#include <iostream>
+#include <osg/Timer>
+
+ossimPlanetServerThread::ossimPlanetServerThread(ossim_uint32 maxQueueSize)
+ :thePollingRatePerSecond(60),
+ theMaxQueueSize(maxQueueSize),
+ theDoneFlag(false),
+ theStartedFlag(false),
+ theQueueMessagesFlag(false)
+{
+}
+
+ossimPlanetServerThread::~ossimPlanetServerThread()
+{
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theChannelList.size();++idx)
+ {
+ if(theChannelList[idx].valid())
+ {
+ theChannelList[idx]->close();
+ theChannelList[idx] = 0;
+ }
+ }
+ theChannelList.clear();
+}
+
+void ossimPlanetServerThread::run()
+{
+ if(theStartedFlag) return;
+ theStartedFlag = true;
+ theDoneFlag = false;
+ while(!theDoneFlag)
+ {
+ std::vector<char> buf(SG_IO_MAX_MSG_SIZE*2);
+ ossim_uint32 idx = 0;
+ std::string msg;
+ bool needToSleep = true;
+ theChannelListMutex.lock();
+ for(idx = 0; idx < theChannelList.size(); ++idx)
+ {
+ int bytesRead = theChannelList[idx]->readline(&buf.front(), buf.size()>>1);
+ if(bytesRead > 0)
+ {
+ needToSleep = false;
+ ossimString s(buf.begin(),
+ buf.begin()+bytesRead);
+ s = s.trim();
+ if(s!="")
+ {
+ // let's first try to see if the message could be handled immediately
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerMutex);
+ ossim_uint32 idx = 0;
+ bool handledFlag = false;
+ for(idx = 0; ((idx < theMessageHandlerList.size())&&!handledFlag); ++idx)
+ {
+ handledFlag = theMessageHandlerList[idx]->handleMessage(s, theChannelList[idx].get());
+ }
+
+ // if it was not handled then just add it to the message queue. Someone may be monitoring
+ // the thread and do not have a message handler callback.
+ //
+ if(!handledFlag&&theQueueMessagesFlag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageQueueMutex);
+ theMessageQueue.push(s);
+ if(theMessageQueue.size() > theMaxQueueSize)
+ {
+ theMessageQueue.pop();
+ }
+ }
+ }
+ }
+ }
+ theChannelListMutex.unlock();
+
+ if(needToSleep)
+ {
+ unsigned int hz = (unsigned int)((1.0/thePollingRatePerSecond)/1.0e-6);
+ microSleep(hz);
+ }
+ }
+ theStartedFlag = false;
+}
+
+int ossimPlanetServerThread::cancel()
+{
+ theDoneFlag = true;
+ return OpenThreads::Thread::cancel();
+}
+
+void ossimPlanetServerThread::setQueueMessagesFlag(bool flag)
+{
+ theQueueMessagesFlag = flag;
+}
+
+bool ossimPlanetServerThread::getQueueMessagesFlag()const
+{
+ return theQueueMessagesFlag;
+}
+
+osg::ref_ptr<SGSocket> ossimPlanetServerThread::addServer(const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType,
+ char delimiter)
+{
+ osg::ref_ptr<SGSocket> result = new SGSocket(host, port, portType);
+ if(result->open(SG_IO_IN))
+ {
+ result->setReadlineDelimiter(delimiter);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChannelListMutex);
+ theChannelList.push_back(result);
+ }
+ else
+ {
+ result = 0;
+ }
+ if(result.valid())
+ {
+ if(theChannelList.size()&&!theStartedFlag)
+ {
+ start();
+ }
+ }
+ return result;
+}
+
+osg::ref_ptr<SGSocket> ossimPlanetServerThread::removeServer(ossim_uint32 idx)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChannelListMutex);
+ osg::ref_ptr<SGSocket> result;
+ if(idx < theChannelList.size())
+ {
+ if(theChannelList[idx].valid())
+ {
+ theChannelList[idx]->close();
+ result = theChannelList[idx];
+ theChannelList.erase(theChannelList.begin()+idx);
+ }
+ }
+ if((theChannelList.size()==0)&&(theStartedFlag))
+ {
+ cancel();
+ }
+
+ return result;
+}
+
+osg::ref_ptr<SGSocket> ossimPlanetServerThread::removeServer(const ossimString& host,
+ const ossimString& port)
+{
+ osg::ref_ptr<SGSocket> result;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChannelListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theChannelList.size(); ++idx)
+ {
+ if((theChannelList[idx]->get_hostname() == host.string())&&
+ (theChannelList[idx]->get_port_str() == port.string()))
+ {
+ theChannelList[idx]->close();
+ result = theChannelList[idx];
+ theChannelList.erase(theChannelList.begin()+idx);
+
+ break;
+ }
+ }
+ }
+ if((theChannelList.size()==0)&&(theStartedFlag))
+ {
+ cancel();
+ }
+
+ return result;
+}
+
+bool ossimPlanetServerThread::setServer(ossim_uint32 idx,
+ const ossimString& host,
+ const ossimString& port,
+ const ossimString& portType)
+{
+ bool result = false;
+
+ if(idx < theChannelList.size())
+ {
+ if(theChannelList[idx].valid())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChannelListMutex);
+// delete theChannelList[idx];
+// theChannelList[idx] = new SGSocket(host, port, portType);
+ theChannelList[idx]->setSocket(host, port, portType);
+ result = theChannelList[idx]->open(SG_IO_IN);
+ }
+ }
+ if(result)
+ {
+ if(theChannelList.size()&&!theStartedFlag)
+ {
+ start();
+ }
+ }
+ return result;
+}
+
+ossimString ossimPlanetServerThread::getPort(ossim_uint32 idx)const
+{
+ ossimString result;
+
+ if(idx < theChannelList.size())
+ {
+ if(theChannelList[idx].valid())
+ {
+ result = theChannelList[idx]->get_port_str();
+ }
+ }
+
+ return result;
+}
+
+ossimString ossimPlanetServerThread::getServer(ossim_uint32 idx)const
+{
+ ossimString result;
+
+ if(idx < theChannelList.size())
+ {
+ if(theChannelList[idx].valid())
+ {
+ result = theChannelList[idx]->get_hostname();
+ }
+ }
+
+ return result;
+}
+
+ossimString ossimPlanetServerThread::getPortType(ossim_uint32 idx)const
+{
+ ossimString result;
+
+ if(idx < theChannelList.size())
+ {
+ if(theChannelList[idx].valid())
+ {
+ result = theChannelList[idx]->get_port_style();
+ }
+ }
+
+ return result;
+}
+
+ossim_uint32 ossimPlanetServerThread::getNumberOfServers()const
+{
+ return theChannelList.size();
+}
+
+bool ossimPlanetServerThread::nextMessage(ossimString& msg)
+{
+ bool result = false;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageQueueMutex);
+ if(!theMessageQueue.empty())
+ {
+ msg = theMessageQueue.front();
+ theMessageQueue.pop();
+ result = true;
+ }
+
+ return result;
+}
+
+void ossimPlanetServerThread::addMessageHandler(osg::ref_ptr<ossimPlanetServerMessageHandler> messageHandler)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerMutex);
+ int idx = findMessageHandler(messageHandler.get());
+
+ if(idx < 0)
+ {
+ theMessageHandlerList.push_back(messageHandler.get());
+ }
+}
+
+void ossimPlanetServerThread::removeMessageHandler(osg::ref_ptr<ossimPlanetServerMessageHandler> messageHandler)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerMutex);
+ int idx = findMessageHandler(messageHandler.get());
+ if(idx >= 0)
+ {
+ theMessageHandlerList.erase(theMessageHandlerList.begin() + idx);
+ }
+}
+
+ossim_uint32 ossimPlanetServerThread::getNumberOfMessageHandlers()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMessageHandlerMutex);
+ return theMessageHandlerList.size();
+}
+
+int ossimPlanetServerThread::findMessageHandler(ossimPlanetServerMessageHandler* handler)const
+{
+
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theMessageHandlerList.size(); ++idx)
+ {
+ if(handler == theMessageHandlerList[idx].get())
+ {
+ return static_cast<int>(idx);
+ }
+ }
+
+ return -1;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetShaderProgramSetup.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetShaderProgramSetup.cpp
new file mode 100644
index 0000000..0b8a36e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetShaderProgramSetup.cpp
@@ -0,0 +1,17 @@
+#include <ossimPlanet/ossimPlanetShaderProgramSetup.h>
+
+osg::ref_ptr<osg::Uniform> ossimPlanetShaderProgramSetup::getUniform(const ossimString& name)
+{
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theUniformList.size(); ++idx)
+ {
+ if(theUniformList[idx]->getName() == name.string())
+ {
+ return theUniformList[idx].get();
+ }
+ }
+
+ return 0;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetSocketNetworkConnection.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetSocketNetworkConnection.cpp
new file mode 100644
index 0000000..22330f7
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetSocketNetworkConnection.cpp
@@ -0,0 +1,186 @@
+
+//#include <assert.h>
+//#include <errno.h>
+#include <string>
+//#include <netdb.h>
+//#include <netinet/in.h>
+//#include <unistd.h>
+//#include <sys/types.h>
+//#include <sys/socket.h>
+#include <ossimPlanet/ossimPlanetSocketNetworkConnection.h>
+#include <ossimPlanet/mkUtils.h>
+#include <ossimPlanet/ossimPlanetDestinationCommandAction.h>
+
+ossimPlanetSocketNetworkConnection::ossimPlanetSocketNetworkConnection(const std::string& hostname, int port, char delimiter) :
+ ossimPlanetNetworkConnection(hostname + ":" + mkUtils::asString(port)),
+ actionDelimiter_(delimiter)
+{
+ theSocket = new ossimPlanetSocketNetworkConnection::ossimPlanetNetSocketRef;
+ if(theSocket->open(true)) // make a tcp stream
+ {
+ theSocket->setBlocking(false);
+ if(theSocket->connect(hostname.c_str(), port) > 0)
+ {
+ error_ = "unable to connect socket";
+
+ }
+ }
+ else
+ {
+ theSocket = 0;
+ error_ = "unable to create socket";
+ }
+
+#if 0
+ // create and connect the socket
+ socket_ = socket(AF_INET, SOCK_STREAM, 0);
+ if (socket_ >= 0) {
+ struct hostent* host = gethostbyname(hostname.c_str());
+ if (host != NULL) {
+ // Initialize the socket address structure
+ struct sockaddr_in connectAddress;
+ memset(&connectAddress, 0, sizeof(connectAddress));
+ memcpy((char *)&connectAddress.sin_addr, host->h_addr, host->h_length);
+ connectAddress.sin_family = host->h_addrtype; // Should be AF_INET
+ connectAddress.sin_port = htons((unsigned short)port);
+
+ // try to connect, repeat if EINTRrupted, abort on any other failure
+ while (connect(socket_, (struct sockaddr*)&connectAddress, sizeof(connectAddress)) < 0) {
+ if (errno != EINTR) {
+ error_ = "unable to connect socket";
+ break;
+ }
+ }
+ } else {
+ error_ = "cannot gethostbyname(\"" + hostname + "\") : " + hstrerror(h_errno);
+ }
+ } else {
+ error_ = "unable to create socket";
+ }
+
+ timeout_.tv_sec = 0;
+ timeout_.tv_usec = 0;
+#endif
+}
+
+ossimPlanetSocketNetworkConnection::~ossimPlanetSocketNetworkConnection()
+{
+ if(theSocket.valid())
+ {
+ theSocket->close();
+ }
+ theSocket = 0;
+#if 0
+ if (socket_ >= 0) {
+ close(socket_);
+ socket_ = -1;
+ }
+#endif
+}
+
+void ossimPlanetSocketNetworkConnection::send(const ossimPlanetAction& a, const std::string& /*destination*/)
+{
+ ossimString code;
+ a.sourceCode(code);
+ if (outBuffer_.empty())
+ {
+ int bytesWritten = theSocket->send(code.c_str(), code.length());
+ if (bytesWritten != (int)code.length())
+ {
+ outBuffer_.append(code.substr(bytesWritten == -1 ? 0 : bytesWritten));
+ outBuffer_.append(1, actionDelimiter_);
+ }
+ else
+ {
+ if (theSocket->send(&actionDelimiter_, 1) != 1)
+ {
+ outBuffer_.append(1, actionDelimiter_);
+ }
+ }
+ }
+ else
+ {
+ outBuffer_.append(code.string());
+ outBuffer_.append(1, actionDelimiter_);
+ attemptToFlushOutBuffer();
+ }
+}
+
+void ossimPlanetSocketNetworkConnection::receive()
+{
+#if 1
+ if(theSocket.valid())
+ {
+ attemptToFlushOutBuffer();
+ std::vector<char> readBuffer(4096);
+ int bytesRead = theSocket->recv(&readBuffer.front(), readBuffer.size());
+ if (bytesRead > 0)
+ {
+ inBuffer_.append(readBuffer.begin(), readBuffer.begin() + bytesRead);
+ }
+ else if (bytesRead == -1)
+ {
+ //std::cerr << "ossimPlanetSocketNetworkConnection::receive() failed to read data. NetworkConnection::name() = " << name_ << std::endl;
+ }
+
+ for (ossim_int64 eoc = inBuffer_.find(actionDelimiter_); eoc != std::string::npos; eoc = inBuffer_.find(actionDelimiter_))
+ {
+ ossimPlanetDestinationCommandAction(inBuffer_.substr(0, eoc),
+ "ossimPlanetSocketNetworkConnection-" + name_).execute();
+ inBuffer_.erase(0, eoc + 1);
+ }
+ }
+#endif
+}
+
+// protected
+
+inline void ossimPlanetSocketNetworkConnection::attemptToFlushOutBuffer()
+{
+ if (!outBuffer_.empty())
+ {
+ int bytesWritten = theSocket->send(outBuffer_.c_str(), outBuffer_.length());
+
+ if (bytesWritten != -1)
+ {
+ outBuffer_.erase(0, bytesWritten);
+ }
+
+ if (outBuffer_.length() > 64*1024)
+ {
+// std::cerr << "Warning: ossimPlanetSocketNetworkConnection " << name_ << " has " << outBuffer_.length() << " bytes of backed up outgoing Actions!" << std::endl;
+ }
+ }
+#if 0
+ if(!theSocket.valid()) return;
+ if (!outBuffer_.empty())
+ {
+ int bytesWritten = theSocket->send(outBuffer_.c_str(), outBuffer_.length());
+// int bytesWritten = theSocket->write(outBuffer_.c_str(), outBuffer_.length());
+
+ if (bytesWritten != -1)
+ {
+ outBuffer_.erase(0, bytesWritten);
+ }
+
+ if (outBuffer_.length() > 64*1024)
+ {
+ std::cerr << "Warning: ossimPlanetSocketNetworkConnection " << name_ << " has " << outBuffer_.length() << " bytes of backed up outgoing Actions!" << std::endl;
+ }
+ }
+#endif
+#if 0
+ assert(socket_ >= 0);
+
+ if (!outBuffer_.empty()) {
+ int bytesWritten = write(socket_, outBuffer_.c_str(), outBuffer_.length());
+ if (bytesWritten != -1)
+ outBuffer_.erase(0, bytesWritten);
+
+ if (outBuffer_.length() > 64*1024)
+ std::cerr << "Warning: ossimPlanetSocketNetworkConnection " << name_ << " has " << outBuffer_.length() << " bytes of backed up outgoing Actions!" << std::endl;
+ }
+#endif
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetSousaLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetSousaLayer.cpp
new file mode 100644
index 0000000..65afeed
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetSousaLayer.cpp
@@ -0,0 +1,749 @@
+#include <ossimPlanet/ossimPlanetSousaLayer.h>
+#include <ossimPlanet/ossimPlanetAction.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetLand.h>
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimPreferences.h>
+#include <osgGA/EventVisitor>
+#include <ostream>
+#include <ossim/base/ossimNotify.h>
+
+class ossimPlanetSousaLayer::ossimPlanetSousaXmlActionOperation : public ossimPlanetOperation
+{
+public:
+ ossimPlanetSousaXmlActionOperation(ossimPlanetSousaLayer* layer, ossimPlanetXmlAction* action)
+ :theLayer(layer),
+ theAction(action)
+ {
+ }
+protected:
+ virtual void run()
+ {
+ theLayer->threadedXmlExecute(*theAction);
+ }
+ ossimPlanetSousaLayer* theLayer;
+ osg::ref_ptr<ossimPlanetXmlAction> theAction;
+};
+
+ossimPlanetSousaLayer::ossimPlanetSousaLayer()
+:theConnectionName(""),
+ theConnectionIp(""),
+ theConnectionPort(""),
+ theConnectionPortType(""),
+theIoThreadReceiverName(":io"),
+theZuiInitializedFlag(false),
+theViewChangedFlag(false),
+theViewMessageRate(30), // default to 30 times per second
+theCameraTestDelay(0),
+theNeedToAddImageGroupFlag(true)
+{
+ theXmlActionThreadQueue = new ossimPlanetOperationThreadQueue();
+ theAnnotationLayer = new ossimPlanetAnnotationLayer;
+ theNodeCallback = new ossimPlanetNodeReraiseCallback(this);
+ theAnnotationLayer->addCallback(theNodeCallback.get());
+ ossimPlanetLayer::addChild(theAnnotationLayer.get());
+ theSousaImageGroup = new ossimPlanetTextureLayerGroup;
+ theSousaImageGroup->setName("OSSIM Socket Image Group");
+}
+
+ossimPlanetSousaLayer::~ossimPlanetSousaLayer()
+{
+ theXmlActionThreadQueue->removeAllOperations();
+ theXmlActionThreadQueue->cancelCurrentOperation();
+ theXmlActionThreadQueue = 0;
+ theAnnotationLayer->removeCallback(theNodeCallback.get());
+ theAnnotationLayer = 0;
+}
+
+
+void ossimPlanetSousaLayer::removeImage(const ossimString& name, const ossimString& id)
+{
+ if(!theSousaImageGroup.valid()) return;
+ osg::ref_ptr<ossimPlanetTextureLayer> namedLayer;
+ if(!name.empty()&&!id.empty())
+ {
+ namedLayer = theSousaImageGroup->findLayerByNameAndId(name, id);
+ }
+ else if(!name.empty())
+ {
+ namedLayer = theSousaImageGroup->findLayerByName(name);
+ }
+ else if(!id.empty())
+ {
+ namedLayer = theSousaImageGroup->findLayerById(id);
+ }
+ if(namedLayer.valid())
+ {
+ namedLayer->remove();
+ }
+}
+
+void ossimPlanetSousaLayer::setIdentity(const ossimString& tempUserName,
+ const ossimString& tempDomain)
+{
+ theUserName = tempUserName;
+ theDomain = tempDomain;
+ sendIdentityMessage();
+}
+
+const ossimString& ossimPlanetSousaLayer::username()const
+{
+ return theUserName;
+}
+
+const ossimString& ossimPlanetSousaLayer::domain()const
+{
+ return theDomain;
+}
+
+void ossimPlanetSousaLayer::xmlExecute(const ossimPlanetXmlAction &a)
+{
+ if(theXmlActionThreadQueue.valid())
+ {
+ ossim_uint32 idx = 0;
+ std::string command = a.command();
+ if(command == "Add")
+ {
+ if(a.xmlNode().valid())
+ {
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ for(idx = 0;idx<children.size();++idx)
+ {
+ osg::ref_ptr<ossimPlanetXmlAction> action = a.duplicateChildAndMaintainAction(idx);
+ osg::ref_ptr<ossimPlanetSousaXmlActionOperation> operation = new ossimPlanetSousaXmlActionOperation(this, action.get());
+
+ ossimString tag = children[idx]->getTag();
+ ossimString groupType = children[idx]->getAttributeValue("groupType");
+ if((tag == "Image")||
+ (groupType=="groundTexture"))
+ {
+ ossimString id = children[idx]->getChildTextValue("id");
+ operation->setId(id);
+ operation->setName("Adding id = " + id);
+ theXmlActionThreadQueue->add(operation.get());
+ }
+ else if((tag == "Placemark")||
+ (groupType == "feature"))
+ {
+ ossimString id = children[idx]->getChildTextValue("id");
+ ossimString name = children[idx]->getChildTextValue("name");
+ operation->setId(id);
+ operation->setName(name);
+ theXmlActionThreadQueue->add(operation.get());
+ }
+ else if(tag == "Group")
+ {
+ ossimString id = children[idx]->getChildTextValue("id");
+ ossimString name = children[idx]->getChildTextValue("name");
+ operation->setId(id);
+ operation->setName(name);
+ ossimString groupType = children[idx]->getAttributeValue("groupType");
+ theXmlActionThreadQueue->add(operation.get());
+ }
+ else
+ {
+ theXmlActionThreadQueue->add(operation.get());
+ }
+ }
+ }
+ }
+ else if(command == "Remove")
+ {
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ if(children.empty())
+ {
+ osg::ref_ptr<ossimPlanetXmlAction> action = (ossimPlanetXmlAction*)a.clone();
+ osg::ref_ptr<ossimPlanetSousaXmlActionOperation> operation = new ossimPlanetSousaXmlActionOperation(this, action.get());
+ ossimString id = a.xmlNode()->getAttributeValue("id");
+ if(!id.empty())
+ {
+ theXmlActionThreadQueue->removeById(id).valid();
+ }
+ theXmlActionThreadQueue->add(operation.get());
+ }
+ else
+ {
+ for(idx = 0;idx<children.size();++idx)
+ {
+ osg::ref_ptr<ossimPlanetXmlAction> action = a.duplicateChildAndMaintainAction(idx);
+ osg::ref_ptr<ossimPlanetSousaXmlActionOperation> operation = new ossimPlanetSousaXmlActionOperation(this, action.get());
+ ossimString id = children[idx]->getAttributeValue("id");
+ if(id.empty())
+ {
+ id = children[idx]->getChildTextValue("id");
+ }
+ if(!id.empty())
+ {
+ theXmlActionThreadQueue->removeById(id).valid();
+ }
+ theXmlActionThreadQueue->add(operation.get());
+ }
+ }
+ }
+ else if(command == "Set")
+ {
+ theXmlActionThreadQueue->add(new ossimPlanetSousaXmlActionOperation(this,(ossimPlanetXmlAction*)a.clone()));
+ }
+ }
+}
+
+void ossimPlanetSousaLayer::threadedXmlExecute(const ossimPlanetXmlAction &a)
+{
+ // OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theXmlActionThreadQueueMutex);
+
+ std::string command = a.command();
+ if(command == "Add")
+ {
+ if(a.xmlNode().valid())
+ {
+ ossim_uint32 idx = 0;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ for(idx = 0;idx<children.size();++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ ossimString groupType = children[idx]->getAttributeValue("groupType");
+ if(tag == "ClientSocket")
+ {
+ setClientSocket(children[idx].get());
+ }
+ else if((tag == "Image")||
+ (groupType=="groundTexture"))
+ {
+ addImageLayer(children[idx].get());
+ }
+ else if((tag == "Placemark")||
+ (groupType == "feature"))
+ {
+ if(theAnnotationLayer.valid())
+ {
+ ossimRefPtr<ossimXmlNode> xmlAction = new ossimXmlNode;
+
+ ossimPlanetXmlAction tempAction;
+ xmlAction->setTag("Add");
+ xmlAction->addChildNode((ossimXmlNode*)children[idx]->dup());
+ tempAction.setXmlNode(xmlAction.get());
+
+ theAnnotationLayer->execute(tempAction);
+ }
+ }
+ else if(tag == "Identity")
+ {
+ ossimString username = children[idx]->getChildTextValue("username");
+ ossimString domain = children[idx]->getChildTextValue("domain");
+
+ setIdentity(username, domain);
+ }
+ else if(tag == "Group")
+ {
+ ossimString groupType = children[idx]->getAttributeValue("groupType");
+ if(groupType == "groundTexture")
+ {
+ }
+ else if(groupType == "feature")
+ {
+ }
+ }
+ }
+ }
+ }
+ else if(command == "Set")
+ {
+ ossim_uint32 idx = 0;
+ ossimString id;
+ ossimString name;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ if(children.size() > 0)
+ {
+ for(idx = 0;idx<children.size();++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ if(tag == "ClientSocket")
+ {
+ setClientSocket(children[idx].get());
+ }
+ else if(tag == "Camera")
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> testDelayLock(theCameraTestDelayMutex);
+ // let's set a 2 frame delay just in case the draw thread is already in the process of visiting us. So on the second visit
+ // we will do a view chnge test
+ //
+ theCameraTestDelay = 10;
+ ossimRefPtr<ossimXmlNode> xmlActionNode = new ossimXmlNode;
+ ossimRefPtr<ossimXmlNode> dupNode = (ossimXmlNode*)(children[idx]->dup());
+ ossimPlanetXmlAction tempAction;
+ xmlActionNode->setTag("Set");
+ xmlActionNode->addAttribute("target", ":navigator");
+ xmlActionNode->addChildNode(dupNode.get());
+ tempAction.setXmlNode(xmlActionNode.get());
+ tempAction.execute();
+ setRedrawFlag(true);
+ theZuiInitializedFlag = true;
+ }
+ else if(tag == "Identity")
+ {
+ ossimString username = children[idx]->getChildTextValue("username");
+ ossimString domain = children[idx]->getChildTextValue("domain");
+
+ setIdentity(username, domain);
+ }
+ else if(tag == "viewMessageRate")
+ {
+ theViewMessageRate = children[idx]->getText().toDouble();
+ }
+ else if(tag =="Placemark")
+ {
+ ossimPlanetXmlAction tempAction;
+ ossimRefPtr<ossimXmlNode> xmlAction = new ossimXmlNode;
+ xmlAction->setTag("Set");
+ xmlAction->addChildNode((ossimXmlNode*)children[idx]->dup());
+ tempAction.setXmlNode(xmlAction.get());
+ theAnnotationLayer->execute(tempAction);
+ }
+ else
+ {
+ id = a.xmlNode()->getAttributeValue("id");
+ if(!id.empty())
+ {
+ ossimPlanetXmlAction tempAction;
+ ossimRefPtr<ossimXmlNode> xmlAction = new ossimXmlNode;
+ xmlAction->setTag("Set");
+ xmlAction->addAttribute("id", id);
+ xmlAction->addChildNode((ossimXmlNode*)children[idx]->dup());
+ tempAction.setXmlNode(xmlAction.get());
+ theAnnotationLayer->execute(tempAction);
+ }
+ }
+ }
+ }
+ }
+ else if(command == "Remove")
+ {
+ if(a.xmlNode().valid())
+ {
+ ossim_uint32 idx = 0;
+ ossimString id;
+ ossimString name;
+ const ossimXmlNode::ChildListType& children = a.xmlNode()->getChildNodes();
+ if(children.size() > 0)
+ {
+ for(idx = 0;idx<children.size();++idx)
+ {
+ ossimString tag = children[idx]->getTag();
+ // check attribute section first for searchables
+ name = children[idx]->getAttributeValue("name");
+ id = children[idx]->getAttributeValue("id");
+ ossimString groupType = children[idx]->getAttributeValue("groupType");
+
+ if(name.empty()&&id.empty())
+ {
+ name = children[idx]->getChildTextValue("name");
+ id = children[idx]->getChildTextValue("id");
+ }
+
+ if((tag == "Image")||
+ (groupType == "groundTexture"))
+ {
+ removeImage(name, id);
+ }
+ else if(tag == "Placemark")
+ {
+ if(theAnnotationLayer.valid())
+ {
+ ossimRefPtr<ossimXmlNode> xmlAction = new ossimXmlNode;
+ ossimPlanetXmlAction tempAction;
+ xmlAction->setTag("Remove");
+ xmlAction->addChildNode((ossimXmlNode*)children[idx]->dup());
+ tempAction.setXmlNode(xmlAction.get());
+ theAnnotationLayer->execute(tempAction);
+ }
+ }
+ else
+ {
+ removeImage(name, id);
+ // do a generalized find and remove
+ }
+ }
+ }
+ else
+ {
+ name = "";
+ id = "";
+ // do generalized remove if the Remove has an id attribute
+ //
+ // basically allow one to do <Remove id="....."/>
+ //
+ if(a.xmlNode()->getAttributeValue(id, "id")||
+ a.xmlNode()->getAttributeValue(name, "name"))
+ {
+ removeImage(name, id);
+ }
+ // wil also send to the Annotation layer to find the ID
+ //
+ if(theAnnotationLayer.valid())
+ {
+ theAnnotationLayer->execute(a);
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetSousaLayer::execute(const ossimPlanetAction &a)
+{
+ const ossimPlanetXmlAction* xmlAction = a.toXmlAction();
+
+ if(xmlAction)
+ {
+ xmlExecute(*xmlAction);
+ }
+}
+
+void ossimPlanetSousaLayer::closeConnections()
+{
+ std::ostringstream out;
+
+ if(!theConnectionName.empty())
+ {
+ out<< "<Remove target=\"" << theIoThreadReceiverName << "\"" << "id=\"" << theConnectionName <<":"<<theConnectionPort << "\"/>";
+ }
+ else
+ {
+ out<< "<Remove target=\"" << theIoThreadReceiverName << "\"" << "id=\"" << theConnectionIp <<":"<<theConnectionPort << "\"/>";
+ }
+ ossimPlanetXmlAction(out.str()).execute();
+
+ theConnectionName = "";
+ theConnectionIp = "";
+ theConnectionPort = "";
+ theConnectionPortType = "";
+ if(theAnnotationLayer.valid())
+ {
+ if(theAnnotationLayer->getNumChildren() > 0)
+ {
+ theAnnotationLayer->removeChild(0, theAnnotationLayer->getNumChildren());
+ }
+ }
+}
+
+void ossimPlanetSousaLayer::traverse(osg::NodeVisitor& nv)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theUpdateMutex);
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(!thePlanet)
+ {
+ thePlanet = ossimPlanet::findPlanet(this);
+ }
+ if(thePlanet)
+ {
+ if(theZuiInitializedFlag)
+ {
+ if(theViewChangedFlag)
+ {
+ sendViewMessage();
+ }
+ }
+ }
+ break;
+ }
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
+ if(ev)
+ {
+ ossimPlanetViewer* viewer = dynamic_cast<ossimPlanetViewer*>(ev->getActionAdapter());
+ if(theNeedToAddImageGroupFlag)
+ {
+ viewer->addImageTexture(theSousaImageGroup.get());
+ theNeedToAddImageGroupFlag = false;
+ }
+ if(viewer&&viewer->currentCamera())
+ {
+ osg::Vec3d currentEye(viewer->currentCamera()->lat(),
+ viewer->currentCamera()->lon(),
+ viewer->currentCamera()->altitude());
+ osg::Vec3d currentHpr(viewer->currentCamera()->heading(),
+ viewer->currentCamera()->pitch(),
+ viewer->currentCamera()->roll());
+ OpenThreads::ScopedLock<OpenThreads::Mutex> testDelayLock(theCameraTestDelayMutex);
+ if(theCameraTestDelay>0)
+ {
+ theEyePosition = currentEye;
+ theEyeOrientation = currentHpr;
+ --theCameraTestDelay;
+ setRedrawFlag(true);
+ }
+ else if(!ossim::almostEqual(theEyePosition[0], currentEye[0])||
+ !ossim::almostEqual(theEyePosition[1], currentEye[1])||
+ !ossim::almostEqual(theEyePosition[2], currentEye[2])||
+ !ossim::almostEqual(theEyeOrientation[0], currentHpr[0])||
+ !ossim::almostEqual(theEyeOrientation[1], currentHpr[1])||
+ !ossim::almostEqual(theEyeOrientation[2], currentHpr[2]))
+ {
+ theEyePosition = currentEye;
+ theEyeOrientation = currentHpr;
+ if(!theViewChangedFlag)
+ {
+ theViewChangeStart = osg::Timer::instance()->tick();
+ }
+ theViewChangedFlag = true;
+ }
+
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ ossimPlanetLayer::traverse(nv);
+}
+
+void ossimPlanetSousaLayer::addImageLayer(const ossimXmlNode* imageObject)
+{
+ ossimString parentId = imageObject->getAttributeValue("parentId");;
+
+#if 0
+ //ossimNotify(ossimNotifyLevel_WARN) << "Testing notifications" << std::endl;
+ if(!thePlanet) return;
+ osg::ref_ptr<ossimPlanetLand> land = thePlanet->land();
+ if(!land.valid())
+ {
+ return;
+ }
+ if(!land->referenceLayer().valid()) return;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> layerGroup;
+ osg::ref_ptr<ossimPlanetTextureLayer> namedLayer;
+ if(!parentId.empty())
+ {
+ namedLayer = land->referenceLayer()->findLayerById(parentId);
+ }
+ if(namedLayer.valid())
+ {
+ layerGroup = namedLayer->asGroup();
+ }
+
+ if(!layerGroup.valid())
+ {
+ layerGroup = land->referenceLayer().get();
+ }
+ if(!layerGroup.valid())
+ {
+ return;
+ }
+#endif
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> layerGroup = theSousaImageGroup.get();
+ osg::ref_ptr<ossimPlanetTextureLayer> namedLayer;
+ if(!parentId.empty())
+ {
+ namedLayer = layerGroup->findLayerById(parentId);
+ }
+ if(namedLayer.valid())
+ {
+ layerGroup = namedLayer->asGroup();
+ }
+
+// if(!layerGroup.valid())
+// {
+// layerGroup = land->referenceLayer().get();
+// }
+ if(!layerGroup.valid())
+ {
+ return;
+ }
+ addImageToGroup(theSousaImageGroup.get(), imageObject);
+}
+
+void ossimPlanetSousaLayer::addImageToGroup(ossimPlanetTextureLayerGroup* group, const ossimXmlNode* imageObject)
+{
+ if(!group) return;
+ ossimString description = imageObject->getChildTextValue("description");
+ ossimString id = imageObject->getChildTextValue("id");
+ ossimString name = imageObject->getChildTextValue("name");
+ ossimFilename filename = imageObject->getChildTextValue("filename").trim();
+ ossimString tag = imageObject->getTag();
+ if(tag=="Image")
+ {
+ // test if the filename for a mapping
+ if(theArchive.valid()&&
+ theArchive->archiveMappingEnabled() )
+ {
+ //ossimNotify(ossimNotifyLevel_WARN) << "Archive mapping is valid and enabled" << std::endl;
+
+ filename = theArchive->matchPath(filename);
+
+ //ossimNotify(ossimNotifyLevel_WARN) << "Archive Filename: " << filename << std::endl;
+ //ossimNotify(ossimNotifyLevel_WARN) << "Archive Result: " << result << std::endl;
+ }
+ //ossimNotify(ossimNotifyLevel_WARN) << "Testing the file: " << filename << std::endl;
+ if(!filename.empty()&&filename.exists())
+ {
+ if(!group->findLayerById(id))
+ {
+// ossimNotify(ossimNotifyLevel_WARN) << "The file is not empty" << std::endl;
+// ossimNotify(ossimNotifyLevel_WARN) << "Filename:" << filename << std::endl;
+
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(filename);
+ if(layer.valid())
+ {
+ layer->setId(id);
+ layer->setDescription(description);
+ layer->setName(name);
+ group->addTop(layer.get());
+ }
+ }
+ else
+ {
+// ossimNotify(ossimNotifyLevel_WARN) << "Failed test and coudn't add image" << std::endl;
+ }
+ }
+ else
+ {
+// ossimNotify(ossimNotifyLevel_INFO) << "Couldn't add file:" << filename <<"--"<< std::endl;
+ }
+ }
+ else if(tag == "Group")
+ {
+ const ossimXmlNode::ChildListType& children = imageObject->getChildNodes();
+ ossimPlanetTextureLayerGroup* newGroup = new ossimPlanetTextureLayerGroup;
+ newGroup->setId(id);
+ newGroup->setDescription(description);
+ newGroup->setName(name);
+ group->addTop(newGroup);
+ ossim_int32 idx = 0;
+ ossim_int32 n = (ossim_int32)children.size();
+ if(n > 0)
+ {
+ for(idx = n-1; idx >= 0;--idx)
+ {
+ addImageToGroup(newGroup, children[idx].get());
+ }
+ }
+ }
+}
+
+
+void ossimPlanetSousaLayer::setConnection(const ossimString& name,
+ const ossimString& ip,
+ const ossimString& port,
+ const ossimString& portType)
+{
+ closeConnections();
+ theConnectionName = name;
+ theConnectionIp = ip;
+ theConnectionPort = port;
+ theConnectionPortType = portType;
+ std::ostringstream out;
+ out
+ << "<Open target=\"" << theIoThreadReceiverName << "\">"
+ << "<ClientSocket>"
+ << "<name>" << name << "</name>"
+ << "<ip>" << ip << "</ip>"
+ << "<port>" << port << "</port>"
+ << "<portType>" << portType << "</portType>"
+ << "</ClientSocket>"
+ << "</Open>";
+ ossimPlanetXmlAction(out.str()).execute();
+ sendIdentityMessage();
+}
+
+void ossimPlanetSousaLayer::setClientSocket(const ossimXmlNode* node)
+{
+ ossimString name, ip, port, portType;
+ node->getChildTextValue(name, "name");
+ node->getChildTextValue(ip, "ip");
+ node->getChildTextValue(port, "port");
+ node->getChildTextValue(portType, "portType");
+ setConnection(name, ip, port, portType);
+}
+
+void ossimPlanetSousaLayer::sendViewMessage()
+{
+ if(theViewMessageRate <FLT_EPSILON)
+ {
+ theViewChangedFlag = false;
+ return;
+ }
+ if(theConnectionIp.empty()&&theConnectionPort.empty()) return;
+ bool canSend = osg::Timer::instance()->delta_s(theViewChangeStart, osg::Timer::instance()->tick()) > (1.0/theViewMessageRate);
+
+ if(canSend)
+ {
+ std::ostringstream out;
+ out
+ << "<SendMessage target='" << theIoThreadReceiverName << "'" << "ioTargetId='" << theConnectionName <<":"<<theConnectionPort << "'" << "id='" << "View'>"
+ << "<Set target=\":idolbridge\">"
+ << "<Camera vref=\"wgs84\">"
+ << "<longitude>" << ossimString::toString(theEyePosition[1]) << "</longitude>"
+ << "<latitude>" << ossimString::toString(theEyePosition[0]) << "</latitude>"
+ << "<altitude>" << ossimString::toString(theEyePosition[2]) << "</altitude>"
+ << "<heading>"<< ossimString::toString(theEyeOrientation[0])<<"</heading>"
+ << "<pitch>"<< ossimString::toString(theEyeOrientation[1])<<"</pitch>"
+ << "<roll>"<< ossimString::toString(theEyeOrientation[2])<<"</roll>"
+ << "<altitudeMode>absolute</altitudeMode>"
+ << "</Camera>"
+ << "</Set>"
+ << "</SendMessage>";
+ ossimPlanetXmlAction(out.str()).execute();
+ theViewChangedFlag = false;
+ }
+ if(theViewChangedFlag)
+ {
+ setRedrawFlag(true);
+ }
+}
+
+void ossimPlanetSousaLayer::setArchive(osg::ref_ptr<ossimPlanetArchive> archive)
+{
+ theArchive = archive;
+}
+
+void ossimPlanetSousaLayer::sendIdentityMessage()
+{
+ if(!theConnectionIp.empty()&&
+ !theConnectionPort.empty())
+ {
+ std::ostringstream out;
+ std::ostringstream outIdentityConnectionHeader;
+ out
+ << "<SendMessage target=\"" << theIoThreadReceiverName << "\"" << "id=\"" << theConnectionName <<":"<<theConnectionPort << "\" forceSend=\"true\">"
+ << "<Set>"
+ << "<Identity>"
+ << "<username>" << theUserName << "</username>";
+
+ if(!theDomain.empty())
+ {
+ out << "<domain>" << theDomain<< "</domain>";
+ }
+ out << "</Identity>"
+ << "</Set>"
+ << "</SendMessage>";
+
+ outIdentityConnectionHeader
+ << "<Set target=\"" << theIoThreadReceiverName << "\"" << "id=\"" << theConnectionName <<":"<<theConnectionPort <<"\">"
+ << "<connectionHeader><![CDATA[<Set>"
+ << "<Identity>"
+ << "<username>" << theUserName << "</username>";
+
+ if(!theDomain.empty())
+ {
+ outIdentityConnectionHeader << "<domain>" << theDomain<< "</domain>";
+ }
+ outIdentityConnectionHeader
+ << "</Identity>"
+ << "</Set>]]></connectionHeader>"
+ << "</Set>";
+
+ ossimPlanetXmlAction(out.str()).execute();
+ ossimPlanetXmlAction(outIdentityConnectionHeader.str()).execute();
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetSrtmElevationDatabase.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetSrtmElevationDatabase.cpp
new file mode 100644
index 0000000..4c9389b
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetSrtmElevationDatabase.cpp
@@ -0,0 +1,804 @@
+#include <ossimPlanet/ossimPlanetSrtmElevationDatabase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimSrtmSupportData.h>
+#include <ossim/projection/ossimImageViewProjectionTransform.h>
+
+ossimPlanetSrtmElevationDatabase::ossimPlanetSrtmElevationDatabase()
+ :ossimPlanetElevationDatabase()
+{
+ theOpenFlag = false;
+ theLocation = "";
+ theMaxOpenFiles = 25;
+ theMinOpenFiles = 20;
+
+// theRenderer = new ossimImageRenderer;
+// theRenderer->getResampler()->setFilterType("bilinear");
+// theProjection = new ossimEquDistCylProjection;
+// theNullHeightValue = -32768.0;
+}
+
+ossimPlanetSrtmElevationDatabase::ossimPlanetSrtmElevationDatabase(const ossimPlanetSrtmElevationDatabase& src)
+ :ossimPlanetElevationDatabase(src),
+ theLocation(src.theLocation),
+ theOpenFlag(src.theOpenFlag),
+ theMaxOpenFiles(src.theMaxOpenFiles),
+ theMinOpenFiles(src.theMinOpenFiles)
+{
+// theMosaic = new ossimOrthoImageMosaic;
+// theRenderer = new ossimImageRenderer;
+// theRenderer->getResampler()->setFilterType("bilinear");
+// theProjection = new ossimEquDistCylProjection;
+}
+
+ossimPlanetSrtmElevationDatabase::~ossimPlanetSrtmElevationDatabase()
+{
+
+}
+
+ossimPlanetTextureLayer* ossimPlanetSrtmElevationDatabase::dup()const
+{
+ return new ossimPlanetSrtmElevationDatabase(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetSrtmElevationDatabase::dupType()const
+{
+ return new ossimPlanetSrtmElevationDatabase;
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetSrtmElevationDatabase::updateExtents()
+{
+
+ theDirtyExtentsFlag = false;
+ return theStateCode;
+}
+
+void ossimPlanetSrtmElevationDatabase::updateStats()const
+{
+ theStats->setTotalTextureSize(0);
+ theDirtyStatsFlag = false;
+
+}
+
+void ossimPlanetSrtmElevationDatabase::resetStats()const
+{
+ theStats->setBytesTransferred(0);
+ theStats->setTotalTextureSize(0);
+}
+
+
+ossimPlanetTextureLayerStateCode ossimPlanetSrtmElevationDatabase::open(const std::string& location)
+{
+ ossimFilename file(location);
+ bool result = false;
+ theLocation = "";
+ theExtents = new ossimPlanetExtents;
+
+ if(file.exists())
+ {
+ if(file.isDir())
+ {
+ ossimDirectory dir;
+
+ if(dir.open(file))
+ {
+ ossimFilename testFile;
+ if(dir.getFirst(testFile))
+ {
+ do
+ {
+ ossimSrtmSupportData supportData;
+ if(supportData.setFilename(testFile))
+ {
+// double minLat = std::floor(supportData.getSouthwestLatitude());
+// double minLon = std::floor(supportData.getSouthwestLongitude());
+// double maxLat = minLat + 1.0;
+// double maxLon = minLon + 1.0;
+// if(!result)
+// {
+ double metersPerPixel = ossimGpt().metersPerDegree().y*supportData.getLatitudeSpacing();
+// theExtents->setMinMaxLatLon(minLat, minLon,
+// maxLat, maxLon);
+ result = true;
+ dirtyExtents(); // make sure parents are marked as dirty
+ if((supportData.getNumberOfLines() == 3601)&&
+ (supportData.getNumberOfSamples() == 3601))
+ {
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 10));
+ setName("SRTM1");
+ setDescription("SRTM 30 meter elevation database");
+ }
+ else if((supportData.getNumberOfLines() == 1201)&&
+ (supportData.getNumberOfSamples() == 1201))
+ {
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 8));
+ setName("SRTM3");
+ setDescription("SRTM 90 meter elevation database");
+ }
+ else if( (supportData.getNumberOfLines() > 3601)&&
+ (supportData.getNumberOfSamples() > 3601))
+ {
+ setName("SRTM");
+ setDescription("SRTM elevation database");
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 8));
+ }
+ else
+ {
+ setName("SRTM");
+ setDescription("SRTM elevation database");
+ theExtents->setMinMaxScale(metersPerPixel, metersPerPixel*std::pow(2.0, 8));
+ }
+// }
+// else
+// {
+// theExtents->combineMinMaxLatLon(minLat, minLon,
+// maxLat, maxLon);
+// }
+ }
+ }while(dir.getNext(testFile)&&!result);
+ }
+ }
+ }
+ }
+
+ theOpenFlag = result;
+ if(theOpenFlag)
+ {
+ theStateCode = ossimPlanetTextureLayer_VALID;
+ theLocation = location;
+ }
+ else
+ {
+ theStateCode = ossimPlanetTextureLayer_NO_SOURCE_DATA;
+ }
+
+ return theStateCode;
+}
+
+bool ossimPlanetSrtmElevationDatabase::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ if(!theOpenFlag)
+ {
+ return false;
+ }
+
+ if(!theEnableFlag)
+ {
+ return false;
+ }
+ ossimPlanetGrid::GridBound bound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ ossimPlanetGrid::GridBound tileBound;
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return false;
+ }
+ }
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ //double deltaLon = (deltaXY[0])/(double)(width);
+
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ ossimPlanetGrid::ModelPoint minLatLon, maxLatLon;
+ grid.modelBound(tileId, minLatLon, maxLatLon);
+ if((gsd.y >= theExtents->getMinScale()) &&
+ (gsd.y <= theExtents->getMaxScale()))
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points);
+ ossim_float64 minModelX, minModelY, maxModelX, maxModelY;
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ minModelX = points[0].x();
+ maxModelX = minModelX;
+ minModelY = points[0].y();
+ maxModelY = minModelY;
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ ++optimizedOutPtr;
+ for(idxPts = 1; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if(optimizedOutPtr->x() < minModelX) minModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->x() > maxModelX) maxModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->y() < minModelY) minModelY = optimizedOutPtr->y();
+ if(optimizedOutPtr->y() > maxModelY) maxModelY = optimizedOutPtr->y();
+ }
+ ossim_int32 wholeMinY = (ossim_int32)std::floor(minModelY);
+ ossim_int32 wholeMinX = (ossim_int32)std::floor(minModelX);
+ ossim_int32 wholeMaxY = (ossim_int32)std::floor(maxModelY);
+ ossim_int32 wholeMaxX = (ossim_int32)std::floor(maxModelX);
+
+
+ ossim_int32 lat = wholeMaxY;
+ ossim_int32 lon = wholeMinX;
+
+
+ // std::vector<ossimDpt> latLonOrigins;
+ std::vector<std::string> latLonOrigins;
+
+ for(;lat >= wholeMinY; --lat)
+ {
+ lon = wholeMinX;
+ for(;lon <= wholeMaxX; ++lon)
+ {
+ ossimFilename filename = buildFilename(lat, lon);
+ if(filename != "")
+ {
+ return true;
+ }
+ }
+ }
+
+ }
+
+ return false;
+}
+osg::ref_ptr<ossimPlanetImage> ossimPlanetSrtmElevationDatabase::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ ossimElevManager* manager = ossimElevManager::instance();
+ double minValue = 999999999.0;
+ double maxValue = -999999999.0;
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ double h = manager->getHeightAboveEllipsoid(ossimGpt((*optimizedOutPtr).y(), (*optimizedOutPtr).x()));
+ if(!ossim::isnan(h))
+ {
+ *bufPtr = h;
+ }
+
+ ++bufPtr;
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+#if 0
+ if(!theOpenFlag)
+ {
+ return 0;
+ }
+
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ osg::ref_ptr<ossimPlanetImage> texture;
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ double deltaLon = (deltaXY[0])/(double)(width);
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y < theExtents->getMaxScale())
+ {
+ ossimPlanetGrid::ModelPoints points;
+ grid.createModelPoints(tileId,
+ width,
+ height,
+ points,
+ padding);
+ ossim_float64 minModelX, minModelY, maxModelX, maxModelY;
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ minModelX = points[0].x();
+ maxModelX = minModelX;
+ minModelY = points[0].y();
+ maxModelY = minModelY;
+ ossimPlanetGrid::ModelPoint* optimizedOutPtr = &points.front();
+ ++optimizedOutPtr;
+ for(idxPts = 1; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if(optimizedOutPtr->x() < minModelX) minModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->x() > maxModelX) maxModelX = optimizedOutPtr->x();
+ if(optimizedOutPtr->y() < minModelY) minModelY = optimizedOutPtr->y();
+ if(optimizedOutPtr->y() > maxModelY) maxModelY = optimizedOutPtr->y();
+ }
+ ossim_int32 wholeMinY = (ossim_int32)std::floor(minModelY);
+ ossim_int32 wholeMinX = (ossim_int32)std::floor(minModelX);
+ ossim_int32 wholeMaxY = (ossim_int32)std::floor(maxModelY);
+ ossim_int32 wholeMaxX = (ossim_int32)std::floor(maxModelX);
+
+
+ ossim_int32 lat = wholeMaxY;
+ ossim_int32 lon = wholeMinX;
+
+
+ // std::vector<ossimDpt> latLonOrigins;
+ std::vector<std::string> latLonOrigins;
+
+ for(;lat >= wholeMinY; --lat)
+ {
+ lon = wholeMinX;
+ for(;lon <= wholeMaxX; ++lon)
+ {
+ ossimFilename filename = buildFilename(lat, lon);
+ if(filename != "")
+ {
+ latLonOrigins.push_back(filename);
+ }
+ }
+ }
+
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/DBL_EPSILON -1;
+ double maxValue = -1.0/DBL_EPSILON +1;
+ if(latLonOrigins.size() == 0)
+ {
+ return 0;
+ }
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfFilesNeeded = latLonOrigins.size();
+ texture = new ossimPlanetImage(tileId);
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width+2*padding,
+ height+2*padding);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ texture->setPadding(padding);
+ for(idx = 0; idx < numberOfFilesNeeded;++idx)
+ {
+ osg::ref_ptr<ossimPlanetSrtmElevationDatabase::SrtmInfo> srtmFile = getInfo(latLonOrigins[idx]);
+
+ if(srtmFile.valid())
+ {
+ ossim_float64 nullHeight = srtmFile->theSrtmHandler->getNullHeightValue();
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ optimizedOutPtr = &points.front();
+ for(idxPts = 0; idxPts < nPoints; ++idxPts,++optimizedOutPtr)
+ {
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&
+ (optimizedOutPtr->y() >= srtmFile->theMinLat)&&
+ (optimizedOutPtr->y() <= srtmFile->theMaxLat)&&
+ (optimizedOutPtr->x() >= srtmFile->theMinLon)&&
+ (optimizedOutPtr->x() <= srtmFile->theMaxLon))
+ {
+ double h = srtmFile->theSrtmHandler->getHeightAboveMSL(ossimGpt(optimizedOutPtr->y(),
+ optimizedOutPtr->x()));
+ if(!ossim::isnan(h)&&
+ (h!=nullHeight))
+ {
+ if(theGeoRefModel.valid())
+ {
+ h+=theGeoRefModel->getGeoidOffset(optimizedOutPtr->y(), optimizedOutPtr->x());
+ }
+ *bufPtr = h;
+ if(h < minValue)
+ {
+ minValue = h;
+ }
+ if(h > maxValue)
+ {
+ maxValue = h;
+ }
+ }
+ else
+ {
+ *bufPtr = 0;
+ }
+ }
+ ++bufPtr;
+ }
+ }
+ }
+ compositeData->validate();
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+ }
+#endif
+ return texture;
+
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetSrtmElevationDatabase::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ if(!theOpenFlag)
+ {
+ return 0;
+ }
+
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+ ossim_uint32 width = utility.getTileWidth();
+ ossim_uint32 height = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row,
+ col);
+
+ if(!theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ return 0;
+ }
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/height;
+ // double deltaLon = deltaX/width;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+
+ if(!theExtents->intersectsScale(gsd.y-FLT_EPSILON,
+ gsd.y+FLT_EPSILON))//gsd.y <= theExtents.theMaxGsd)
+ {
+ return 0;
+ }
+
+ double minSubRectLat = ossim::max(theExtents->getMinLat(),
+ minLat);
+ double minSubRectLon = ossim::max(theExtents->getMinLon(),
+ minLon);
+ double maxSubRectLat = ossim::min(theExtents->getMaxLat(),
+ maxLat);
+ double maxSubRectLon = ossim::min(theExtents->getMaxLon(),
+ maxLon);
+ ossim_int32 wholeMinLat = (ossim_int32)std::floor(minSubRectLat);
+ ossim_int32 wholeMinLon = (ossim_int32)std::floor(minSubRectLon);
+ ossim_int32 wholeMaxLat = (ossim_int32)std::floor(maxSubRectLat);
+ ossim_int32 wholeMaxLon = (ossim_int32)std::floor(maxSubRectLon);
+
+
+ ossim_int32 lat = wholeMaxLat;
+ ossim_int32 lon = wholeMinLon;
+
+// ossim_uint32 addedFiles = 0;
+
+// std::vector<ossimDpt> latLonOrigins;
+ std::vector<std::string> latLonOrigins;
+
+ for(;lat >= wholeMinLat; --lat)
+ {
+ lon = wholeMinLon;
+ for(;lon <= wholeMaxLon; ++lon)
+ {
+ ossimFilename filename = buildFilename(lat, lon);
+ if(filename != "")
+ {
+ latLonOrigins.push_back(filename);
+ }
+ }
+ }
+
+ if(latLonOrigins.size() == 0)
+ {
+ return 0;
+ }
+
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfFilesNeeded = latLonOrigins.size();
+ texture = new ossimPlanetImage(ossimPlanetTerrainTileId(0,
+ level,
+ col,
+ row));
+ ossimRefPtr<ossimImageData> compositeData = new ossimImageData(0,
+ OSSIM_FLOAT32,
+ 1,
+ width,
+ height);
+ compositeData->setNullPix(OSSIMPLANET_NULL_HEIGHT, 0);
+ compositeData->initialize();
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ utility.createGridPoints(points,
+ level,
+ row,
+ col,
+ height,
+ width);
+
+ ossim_uint32 idxPts = 0;
+ ossim_uint32 nPoints = points.size();
+ osg::Vec3d latLonPoint;
+ double minValue = 1.0/DBL_EPSILON -1;
+ double maxValue = -1.0/DBL_EPSILON +1;
+
+ for(idx = 0; idx < numberOfFilesNeeded;++idx)
+ {
+
+ osg::ref_ptr<ossimPlanetSrtmElevationDatabase::SrtmInfo> srtmFile = getInfo(latLonOrigins[idx]);
+
+ if(srtmFile.valid())
+ {
+ ossim_float32* bufPtr = (ossim_float32*)compositeData->getBuf();
+ for(idxPts = 0; idxPts < nPoints; ++idxPts)
+ {
+ utility.getLatLon(latLonPoint, points[idxPts]);
+ if((*bufPtr == OSSIMPLANET_NULL_HEIGHT)&&
+ (latLonPoint[0] >= srtmFile->theMinLat)&&
+ (latLonPoint[0] <= srtmFile->theMaxLat)&&
+ (latLonPoint[1] >= srtmFile->theMinLon)&&
+ (latLonPoint[1] <= srtmFile->theMaxLon))
+ {
+ utility.getLatLon(latLonPoint, points[idxPts]);
+ double h = srtmFile->theSrtmHandler->getHeightAboveMSL(ossimGpt(latLonPoint[0],
+ latLonPoint[1]));
+ if(!ossim::isnan(h))
+ {
+ *bufPtr = h;
+ if(*bufPtr < minValue)
+ {
+ minValue = *bufPtr;
+ }
+ if(*bufPtr > maxValue)
+ {
+ maxValue = *bufPtr;
+ }
+ }
+ }
+ ++bufPtr;
+ }
+ }
+ }
+ compositeData->validate();
+
+
+ if(compositeData->getDataObjectStatus() != OSSIM_EMPTY)
+ {
+ texture->fromOssimImage(compositeData, false);
+
+ if(minValue < maxValue)
+ {
+ texture->setMinMax(minValue, maxValue);
+ }
+ }
+ else
+ {
+ texture = 0;
+ }
+
+ return texture;
+}
+
+osg::ref_ptr<ossimPlanetSrtmElevationDatabase::SrtmInfo> ossimPlanetSrtmElevationDatabase::getInfo(const std::string& srtmName)
+{
+ SrtmFilePointerList::iterator iter = theFilePointers.find(srtmName);
+
+ if(iter != theFilePointers.end())
+ {
+ iter->second->theTimeStamp = osg::Timer::instance()->tick();
+
+ return iter->second;
+ }
+ osg::ref_ptr<SrtmInfo> info = new SrtmInfo;
+
+ ossimFilename srtmFile = ossimFilename(theLocation).dirCat(ossimFilename(srtmName));
+ ossimSrtmSupportData supportData;
+ if(supportData.setFilename(srtmFile))
+ {
+ info->theMinLat = std::floor(supportData.getSouthwestLatitude());
+ info->theMinLon = std::floor(supportData.getSouthwestLongitude());
+ info->theMaxLat = info->theMinLat + 1.0;
+ info->theMaxLon = info->theMinLon + 1.0;
+ }
+ else
+ {
+ return 0;
+ }
+
+ info->theTimeStamp = osg::Timer::instance()->tick();
+ info->theFilename = srtmFile.string();
+ info->theSrtmHandler = new ossimSrtmHandler();
+ info->theSrtmHandler->open(srtmFile);
+ theFilePointers.insert(std::make_pair(srtmName, info));
+ shrinkFilePointers();
+
+ return info;
+}
+
+void ossimPlanetSrtmElevationDatabase::shrinkFilePointers()
+{
+ if(theFilePointers.size() <= theMaxOpenFiles) return;
+
+ const osg::Timer* timer = osg::Timer::instance();
+
+ osg::Timer_t currentTime = timer->tick();
+
+ while((theFilePointers.size()>0) &&
+ (theFilePointers.size() > theMinOpenFiles))
+ {
+ SrtmFilePointerList::iterator iter = theFilePointers.begin();
+ SrtmFilePointerList::iterator currentLargestTimeDelta = iter;
+ double delta = 0.0;
+ while(iter!=theFilePointers.end())
+ {
+ double testDelta = timer->delta_m(currentLargestTimeDelta->second->theTimeStamp, currentTime);
+ if(testDelta > delta)
+ {
+ currentLargestTimeDelta = iter;
+ delta = testDelta;
+ }
+ ++iter;
+ }
+
+ if(currentLargestTimeDelta != theFilePointers.end())
+ {
+ theFilePointers.erase(currentLargestTimeDelta);
+ }
+ }
+}
+
+ossimFilename ossimPlanetSrtmElevationDatabase::buildFilename(double lat, double lon)const
+{
+ ossimFilename srtmFileBasename;
+
+ int ilat = static_cast<int>(floor(lat));
+ if (ilat < 0)
+ {
+ srtmFileBasename = "S";
+ }
+ else
+ {
+ srtmFileBasename = "N";
+ }
+
+ ilat = abs(ilat);
+ std::ostringstream os1;
+
+ os1 << std::setfill('0') << std::setw(2) <<ilat;
+
+ srtmFileBasename += os1.str().c_str();
+
+ int ilon = static_cast<int>(floor(lon));
+
+ if (ilon < 0)
+ {
+ srtmFileBasename += "W";
+ }
+ else
+ {
+ srtmFileBasename += "E";
+ }
+
+ ilon = abs(ilon);
+ std::ostringstream os2;
+ os2 << std::setfill('0') << std::setw(3) << ilon;
+
+ srtmFileBasename += os2.str().c_str();
+ srtmFileBasename.setExtension(".hgt");
+
+ ossimFilename loc(theLocation);
+ if(!loc.dirCat(srtmFileBasename).exists())
+ {
+ srtmFileBasename.setExtension(".HGT");
+ if(!loc.dirCat(srtmFileBasename).exists())
+ {
+ srtmFileBasename = srtmFileBasename.downcase();
+
+ if(!loc.dirCat(srtmFileBasename).exists())
+ {
+ srtmFileBasename = "";
+ }
+ }
+ }
+
+ return srtmFileBasename;
+}
+
+osg::ref_ptr<ossimPlanetSrtmElevationDatabase::SrtmInfo> ossimPlanetSrtmElevationDatabase::findSrtmInfo(const std::string& srtmName)
+{
+ SrtmFilePointerList::iterator iter = theFilePointers.find(srtmName);
+
+ if(iter != theFilePointers.end())
+ {
+ iter->second->theTimeStamp = osg::Timer::instance()->tick();
+ return iter->second;
+ }
+
+ return 0;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetStandardTextureLayerFactory.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetStandardTextureLayerFactory.cpp
new file mode 100644
index 0000000..5b1450b
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetStandardTextureLayerFactory.cpp
@@ -0,0 +1,207 @@
+#include <ossimPlanet/ossimPlanetStandardTextureLayerFactory.h>
+#include <ossimPlanet/ossimPlanetOssimImageLayer.h>
+#include <ossimPlanet/ossimPlanetWmsImageLayer.h>
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <OpenThreads/ScopedLock>
+#include <ossim/base/ossimKeywordNames.h>
+#include <sstream>
+#include <wms/wmsUrl.h>
+
+ossimPlanetStandardTextureLayerFactory* ossimPlanetStandardTextureLayerFactory::theInstance=0;
+
+ossimPlanetStandardTextureLayerFactory::ossimPlanetStandardTextureLayerFactory()
+{
+ theInstance = this;
+}
+
+ossimPlanetStandardTextureLayerFactory* ossimPlanetStandardTextureLayerFactory::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetStandardTextureLayerFactory;
+ }
+
+ return theInstance;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetStandardTextureLayerFactory::createLayer(const ossimString& name, bool openAllEntriesFlag)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ osg::ref_ptr<ossimPlanetTextureLayer> result;
+
+ ossimFilename filename = name;
+
+ if(filename.exists())
+ {
+ return createLayerFromFilename(filename, openAllEntriesFlag);
+ }
+ ossimKeywordlist kwl;
+ std::istringstream in(name);
+
+ if(kwl.parseStream(in))
+ {
+ return createLayerFromKwl(kwl);
+ }
+ if((name == "ossimPlaneTextureLayerGroup")||
+ (name == "group"))
+ {
+ return new ossimPlanetTextureLayerGroup;
+ }
+#ifndef OSGPLANET_WITHOUT_WMS
+ else if((name == "ossimPlanetWmsImageLayer")||
+ (name == "wms"))
+ {
+ return new ossimPlanetWmsImageLayer;
+ }
+#endif
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetStandardTextureLayerFactory::createLayerFromFilename(const ossimFilename& name, bool openAllEntriesFlag)const
+{
+ osg::ref_ptr<ossimPlanetOssimImageLayer> imageLayer = new ossimPlanetOssimImageLayer;
+ imageLayer->openImage(name);
+ if(!imageLayer->isStateSet(ossimPlanetTextureLayer_NO_SOURCE_DATA))
+ {
+ if(openAllEntriesFlag&&imageLayer->isMultiEntry())
+
+ {
+ return imageLayer->groupAllEntries().get();
+ }
+ else
+ {
+ return imageLayer.get();
+ }
+ }
+
+ return 0;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetStandardTextureLayerFactory::createLayerFromKwl(const ossimKeywordlist& kwl,
+ const ossimString& prefix)const
+{
+ if(kwl.find(prefix, "archive0.type"))
+ {
+ return createLayerFromOldKwl(kwl, prefix);
+ }
+
+ return 0;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetStandardTextureLayerFactory::createLayerFromOldKwl(const ossimKeywordlist& kwl,
+ const ossimString& prefix)const
+{
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> groupLayer = new ossimPlanetTextureLayerGroup;
+
+ ossimString archiveKey;
+ ossimString archive = kwl.find(prefix, "archiv0.type");
+ unsigned int idx = 0;
+ bool done = false;
+ while(!done)
+ {
+ stringstream s;
+ s << "archive" << idx << ".";
+ archiveKey = s.str();
+
+ // we will need to move all this to an archive factory
+ // later. For now we will hard code a local and remote archive
+ // creations here.
+ //
+ ossimString archiveType = kwl.find(prefix+archiveKey, "type");
+ if(archiveType == "local")
+ {
+ ossimString localPrefix = archiveKey;
+ osg::ref_ptr<ossimPlanetTextureLayerGroup> groupLocal = new ossimPlanetTextureLayerGroup;
+ int idx = 0;
+ ossimFilename file;
+ bool doneLocal = false;
+ while(!doneLocal)
+ {
+ std::stringstream out;
+ out << "file" << idx;
+
+ file = kwl.find(localPrefix, out.str().c_str());
+ if((file!="")&&(file.exists()))
+ {
+ osg::ref_ptr<ossimPlanetOssimImageLayer> layer = new ossimPlanetOssimImageLayer;
+ layer->openImage(file);
+ if(!layer->isStateSet(ossimPlanetTextureLayer_NO_SOURCE_DATA)&&
+ !layer->isStateSet(ossimPlanetTextureLayer_NO_GEOM))
+ {
+ groupLocal->addBottom(layer.get());
+ }
+ }
+ else
+ {
+ doneLocal = true;
+ }
+ ++idx;
+ }
+ if(groupLocal->numberOfLayers() > 0)
+ {
+ groupLayer->addBottom(groupLocal.get());
+ }
+// ossimPlanetTextureArchive* archive = new ossimPlanetOssimArchive;
+// archive->loadState(kwl,
+// prefix+archiveKey);
+// addArchive(archive);
+ }
+ else if(archiveType == "wms")
+ {
+#ifndef OSGPLANET_WITHOUT_WMS
+ osg::ref_ptr<ossimPlanetWmsImageLayer> layer = new ossimPlanetWmsImageLayer;
+
+ ossimString server = kwl.find(prefix+archiveKey, "server");
+ ossimString cache = kwl.find(prefix+archiveKey, "cache_dir");
+
+ if(!server.empty())
+ {
+ layer->setServer(server);
+ if(!cache.empty())
+ {
+ layer->setCacheDirectory(cache);
+ }
+ groupLayer->addBottom(layer.get());
+
+ }
+
+// ossimPlanetTextureArchive* archive = new ossimPlanetWmsArchive;
+
+// archive->loadState(kwl,
+// prefix+archiveKey);
+// addArchive(archive);
+#endif
+ }
+ else if(archiveType == "background_wms")
+ {
+#ifndef OSGPLANET_WITHOUT_WMS
+// ossimPlanetTextureArchive* background = new ossimPlanetWmsArchive;
+// background->addCallback(theArchiveCallback.get());
+// background->loadState(kwl,
+// prefix+archiveKey);
+// setBackgroundArchive(background);
+#endif
+ }
+ else if(archiveType == "background_local")
+ {
+// ossimPlanetTextureArchive* background = new ossimPlanetOssimArchive;
+// background->addCallback(theArchiveCallback.get());
+// background->loadState(kwl,
+// prefix+archiveKey);
+// setBackgroundArchive(background);
+ }
+ else
+ {
+ done = true;
+ }
+
+ ++idx;
+ }
+
+ if(groupLayer->numberOfLayers() < 1)
+ {
+ groupLayer = 0;
+ }
+
+ return groupLayer.get();
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTerrain.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrain.cpp
new file mode 100644
index 0000000..f3ae176
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrain.cpp
@@ -0,0 +1,1716 @@
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <OpenThreads/ScopedLock>
+#include <osg/NodeVisitor>
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <ossim/elevation/ossimElevSourceFactory.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <ossimPlanet/ossimPlanetTerrainGeometryTechnique.h>
+#include <ossimPlanet/ossimPlanetGeoRefModel.h>
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <ossimPlanet/ossimPlanetElevationRegistry.h>
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetOssimElevationDatabase.h>
+#include <osg/io_utils>
+#include <osg/GraphicsContext>
+#include <osgGA/EventVisitor>
+#include <osgUtil/IntersectionVisitor>
+#include <osgUtil/IntersectVisitor>
+#include <osgUtil/IncrementalCompileOperation>
+#include <stack>
+#include <set>
+
+struct ossimPlanetDatabasePagerCompileCompletedCallback : public osgUtil::IncrementalCompileOperation::CompileCompletedCallback
+{
+ ossimPlanetDatabasePagerCompileCompletedCallback(ossimPlanetTerrain* terrain, ossimPlanetTileRequest* request)
+ :m_terrain(terrain), m_request(request){}
+
+ virtual bool compileCompleted(osgUtil::IncrementalCompileOperation::CompileSet* /* compileSet */)
+ {
+ //std::cout << "COMPILE COMPLETED\n";
+ m_terrain->addRequestToReadyToApplyQueue(m_request.get());
+ return true;
+ }
+
+ osg::ref_ptr<ossimPlanetTerrain> m_terrain;
+ osg::ref_ptr<ossimPlanetTileRequest> m_request;
+};
+
+class ossimPlanetTerrain::TextureCallback : public ossimPlanetTextureLayerCallback
+{
+public:
+ TextureCallback(ossimPlanetTerrain* terrain)
+ :theTerrain(terrain)
+ {
+ }
+
+ void setTerrain(ossimPlanetTerrain* value)
+ {
+ theTerrain = value;
+ }
+ virtual void refreshExtent(osg::ref_ptr<ossimPlanetExtents> extent)
+ {
+ if(theTerrain)
+ {
+ theTerrain->refreshImageLayers(extent.get());
+ }
+ }
+ virtual void layerAdded(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+ {
+ if(theTerrain)
+ {
+ refreshExtent(layer->getExtents().get());
+ }
+ }
+ virtual void layerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ osg::ref_ptr<ossimPlanetTextureLayer> parent)
+ {
+ if(theTerrain)
+ {
+ // only refresh if it was originally enabled
+ if(layer->getEnableFlag())
+ {
+ osg::ref_ptr<ossimPlanetExtents> extents = new ossimPlanetExtents(*layer->getExtents());
+ if(parent.valid())
+ {
+ osg::ref_ptr<ossimPlanetExtents> parentExtents = parent->getExtents();
+ if(parentExtents.valid())
+ {
+ extents->combineScale(parentExtents->getMinScale(),
+ parentExtents->getMaxScale());
+ }
+ }
+ refreshExtent(extents.get());
+ }
+ }
+ }
+ virtual void propertyChanged(const ossimString& name,
+ const ossimPlanetTextureLayer* object)
+ {
+ if(object&&name.contains("enable"))
+ {
+ if(object->getExtents().valid())
+ {
+ osg::ref_ptr<ossimPlanetExtents> extents = new ossimPlanetExtents(*object->getExtents());
+ const ossimPlanetTextureLayerGroup* parent = object->getParent(0);
+ if(parent)
+ {
+ osg::ref_ptr<ossimPlanetExtents> parentExtents = parent->getExtents();
+ if(parentExtents.valid())
+ {
+ extents->combineScale(parentExtents->getMinScale(),
+ parentExtents->getMaxScale());
+ }
+ }
+
+ refreshExtent(extents);
+ }
+ }
+ }
+
+protected:
+ ossimPlanetTerrain* theTerrain;
+};
+
+
+class CountVisitor : public osg::NodeVisitor
+{
+public:
+ CountVisitor()
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+ {
+ theCullCount = 0;
+ theNodeCount = 0;
+ }
+ virtual void apply(osg::Node& node)
+ {
+#if 0
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(&node);
+ if(tile)
+ {
+ if(tile->culledFlag())
+ {
+ ++theCullCount;
+ }
+ ++theNodeCount;
+ }
+#else
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(&node);
+ if(tile&&tile->culledFlag())
+ {
+ std::stack<ossimPlanetTerrainTile*> tileStack;
+ tileStack.push(tile);
+ ossimPlanetTerrainTile* current;
+ ossim_uint32 idx = 0;
+ while(!tileStack.empty())
+ {
+ current = tileStack.top();
+ tileStack.pop();
+ for(idx = 0; idx < current->getNumChildren();++idx)
+ {
+ ossimPlanetTerrainTile* t = (ossimPlanetTerrainTile*)current->getChild(idx);
+ if(t)
+ {
+ tileStack.push(t);
+ ++ theCullCount;
+ ++theNodeCount;
+ }
+ }
+ }
+ ++theNodeCount;
+ ++theCullCount;
+ return;
+ }
+ if(tile)
+ {
+ ++theNodeCount;
+ }
+#endif
+ traverse(node);
+ }
+ ossim_uint32 theCullCount;
+ ossim_uint32 theNodeCount;
+};
+
+class GatherChildrenVisitor : public osg::NodeVisitor
+{
+public:
+ GatherChildrenVisitor()
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+ {
+ }
+ typedef std::stack<osg::ref_ptr<ossimPlanetTerrainTile> > TileStack;
+ virtual void apply(osg::Node& node)
+ {
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(&node);
+ if(tile)
+ {
+ theGatheredChildren.push(tile);
+ }
+ traverse(node);
+ }
+ TileStack& gatheredChildren()
+ {
+ return theGatheredChildren;
+ }
+protected:
+ TileStack theGatheredChildren;
+};
+
+class RemoveChildrenFromGraphVisitor : public osg::NodeVisitor
+{
+public:
+ RemoveChildrenFromGraphVisitor(ossimPlanetTerrain* terrain, ossim_int64 frameNumber, ossim_int64 delta=2)
+ :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ theTerrain(terrain),
+ theFrameNumber(frameNumber),
+ theCullDelta(delta)
+ {
+ }
+ virtual void apply(osg::Node& node)
+ {
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(&node);
+ if(tile)
+ {
+ if(ossim::abs((tile->frameNumber()-theFrameNumber)) > theCullDelta)
+ {
+ theTerrain->removeTerrainTileFromGraph(tile);
+ return;
+ }
+ }
+ traverse(node);
+ }
+ void setFrameNumber(ossim_int64 num)
+ {
+ theFrameNumber = num;
+ }
+
+protected:
+ ossimPlanetTerrain* theTerrain;
+ ossim_int64 theFrameNumber;
+ ossim_int64 theCullDelta;
+};
+
+void ossimPlanetTerrain::UpdateTileCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+ traverse(node,nv);
+ update(dynamic_cast<ossimPlanetTerrainTile*>(node), nv);
+}
+
+void ossimPlanetTerrain::UpdateTileCallback::update(ossimPlanetTerrainTile* /* tile */,
+ osg::NodeVisitor* /* nv */)
+{
+}
+
+void ossimPlanetTerrain::CullTileCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+ traverse(node,nv);
+}
+
+void ossimPlanetTerrain::CullTileCallback::cull(ossimPlanetTerrainTile* /* tile */,
+ osg::NodeVisitor* /* nv */)
+{
+}
+
+ossimPlanetTerrain::ossimPlanetTerrain()
+:theResetRootsFlag(true),
+theLastFrameNumber(-1),
+theTextureTileWidth(256),
+theTextureTileHeight(256),
+theElevationTileWidth(9),//2^n + 1
+theElevationTileHeight(9), //2^n + 1
+theSplitMergeLodScale(3.0),
+theElevationExaggeration(1.0),
+theMinimumTimeToCompilePerFrame(.003),// 3 milliseconds
+thePrecompileEnabledFlag(true),
+theElevationEnabledFlag(true),
+theFalseEyeFlag(false),
+theFalseEye(0.0,0.0,0.0),
+thePriorityPointFlag(false),
+thePriorityPoint(0.0,0.0,0.0)
+{
+ theElevationCacheShrinkOperation = new ossimPlanetImageCacheShrinkOperation;
+ theCacheShrinkThreadQueue = new ossimPlanetOperationThreadQueue;
+ theElevationLayer = new ossimPlanetElevationDatabaseGroup;
+ theElevationLayer->setFillNullWithGeoidOffsetFlag(true);
+ theElevationLayer->setGeoRefModel(theModel.get());
+ theLastApplyToGraphFrameNumber = -1;
+ theMaxNumberOfOperationsToApplyToGraphPerFrame = 5;
+ theTextureCallback = new ossimPlanetTerrain::TextureCallback(this);
+ theTerrainTechnique = new ossimPlanetTerrainGeometryTechnique();
+ theElevationQueue = new ossimPlanetTileRequestThreadQueue;
+ theTextureQueue = new ossimPlanetTileRequestThreadQueue;
+ theTextureLayers.push_back(new ossimPlanetTextureLayerGroup());
+ theTextureLayers[0]->addCallback(theTextureCallback.get());
+ theSplitQueue = new ossimPlanetTileRequestThreadQueue();
+ theMergeQueue = new ossimPlanetTileRequestQueue();
+ theMaxTimeToSplit = 0.0;
+ theMaxTimeToMerge = 2.5;
+ setGrid(new ossimPlanetAdjustableCubeGrid());
+ theSplitMergeMetricType = DISTANCE_METRIC;
+ theSplitPixelMetric = 8;
+ theMergePixelMetric = 4;
+ setCullAmountType(HIGH_CULL);
+}
+
+ossimPlanetTerrain::ossimPlanetTerrain(ossimPlanetGrid* grid)
+:theResetRootsFlag(true),
+theGrid(grid),
+theLastFrameNumber(-1),
+theTextureTileWidth(256),
+theTextureTileHeight(256),
+theElevationTileWidth(9),//2^n + 1
+theElevationTileHeight(9), //2^n + 1
+theSplitMergeLodScale(3.0),
+theElevationExaggeration(1.0),
+theMinimumTimeToCompilePerFrame(.003),// 3 milliseconds
+thePrecompileEnabledFlag(true),
+theElevationEnabledFlag(true),
+theFalseEyeFlag(false),
+theFalseEye(0.0,0.0,0.0),
+thePriorityPointFlag(false),
+thePriorityPoint(0.0,0.0,0.0)
+{
+ theElevationCacheShrinkOperation = new ossimPlanetImageCacheShrinkOperation;
+ theCacheShrinkThreadQueue = new ossimPlanetOperationThreadQueue;
+ theElevationLayer = new ossimPlanetElevationDatabaseGroup;
+ theElevationLayer->setFillNullWithGeoidOffsetFlag(true);
+ theElevationLayer->setGeoRefModel(theModel.get());
+ theLastApplyToGraphFrameNumber = -1;
+ theMaxNumberOfOperationsToApplyToGraphPerFrame= 5;
+ theTextureCallback = new ossimPlanetTerrain::TextureCallback(this);
+ theTerrainTechnique = new ossimPlanetTerrainGeometryTechnique();
+ theTextureLayers.push_back(new ossimPlanetTextureLayerGroup());
+ theTextureLayers[0]->addCallback(theTextureCallback.get());
+ theElevationQueue = new ossimPlanetTileRequestThreadQueue;
+ theTextureQueue = new ossimPlanetTileRequestThreadQueue;
+
+ // make these support priority queues
+ //
+ theSplitQueue = new ossimPlanetTileRequestThreadQueue();
+ theMergeQueue = new ossimPlanetTileRequestQueue();
+ theMaxTimeToSplit = 0.0;
+ theMaxTimeToMerge = 2.5;
+ theSplitMergeMetricType = DISTANCE_METRIC;
+ theSplitPixelMetric = 8;
+ theMergePixelMetric = 4;
+ setCullAmountType(HIGH_CULL);
+}
+
+ossimPlanetTerrain::~ossimPlanetTerrain()
+{
+ theTextureLayers[0]->removeCallback(theTextureCallback.get());
+
+ if(theElevationQueue.valid())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockElevationQueue(theElevationQueueMutex);
+ theElevationQueue->removeAllOperations();
+ theElevationQueue->cancel();
+ theElevationQueue = 0;
+ }
+ if(theTextureQueue.valid())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockTextureQueue(theTextureQueueMutex);
+ theTextureQueue->removeAllOperations();
+ theTextureQueue->cancel();
+ theTextureQueue = 0;
+ }
+ if(theSplitQueue.valid())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockSplitQueue(theSplitQueueMutex);
+ theSplitQueue->removeAllOperations();
+ theSplitQueue->cancel();
+ theSplitQueue = 0;
+ }
+ if(theMergeQueue.valid())
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lockMergeQueue(theMergeQueueMutex);
+ theMergeQueue->removeAllOperations();
+ theMergeQueue = 0;
+ }
+
+ theNeedToCompileQueue.clear();
+ theReadyToApplyToGraphQueue.clear();
+ theReadyToApplyToGraphNewNodesQueue.clear();
+
+ {
+ osg::Group::removeChildren(0, getNumChildren());
+ //OpenThreads::ScopedLock<OpenThreads::Mutex> lockTileSet(theTileSetMutex);
+ theTileSet.clear();
+ }
+ if(theElevationCache.valid())
+ {
+ theElevationCache->clean();
+ theElevationCache = 0;
+ }
+}
+
+void ossimPlanetTerrain::setTerrainTechnique(ossimPlanetTerrainTechnique* technique)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theResetRootsFlag = true;
+ theTerrainTechnique = technique;
+}
+
+ossimPlanetTerrainTechnique* ossimPlanetTerrain::newTechnique()
+{
+ ossimPlanetTerrainTechnique* result = 0;
+
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->setGrid(theGrid.get());
+ if(thePlanet)
+ {
+ theTerrainTechnique->setModel(thePlanet->model().get());
+ }
+ result = (ossimPlanetTerrainTechnique*)theTerrainTechnique->clone(osg::CopyOp::SHALLOW_COPY);
+ }
+
+ return result;
+}
+
+void ossimPlanetTerrain::setElevationEnabledFlag(bool flag)
+{
+ bool refresh = elevationEnabledFlag()!=flag;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theElevationEnabledFlag = flag;
+ }
+ if(refresh)
+ {
+ elevationLayer()->setEnableFlag(theElevationEnabledFlag);
+ theElevationCache->setEnabledFlag(flag);
+ }
+}
+
+bool ossimPlanetTerrain::elevationEnabledFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theElevationEnabledFlag;
+}
+
+void ossimPlanetTerrain::setDatabasePager(osgDB::DatabasePager* pager)
+{
+ thePager = pager;
+}
+
+void ossimPlanetTerrain::initElevation()
+{
+#if 1
+ ossim_uint32 numberOfDatabases = ossimElevManager::instance()->getNumberOfElevationDatabases();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < numberOfDatabases; ++idx)
+ {
+ ossimRefPtr<ossimElevationDatabase> database = ossimElevManager::instance()->getElevationDatabase(idx);
+ if(database.valid())
+ {
+ ossimPlanetOssimElevationDatabase* planetDatabase = new ossimPlanetOssimElevationDatabase;
+ planetDatabase->setDatabase(database.get());
+ addElevation(planetDatabase);
+ }
+ }
+#else
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfDatabases = ossimElevManager::instance()->getNumberOfElevationDatabases();
+ for(idx = 0; idx < numberOfDatabases; ++idx)
+ {
+ const ossimRefPtr<ossimElevationDatabase> database = ossimElevManager::instance()->getElevationDatabase(idx);
+
+ if(database.valid())
+ {
+ ossimFilename directory = ossimFilename(database->getConnectionString());
+ addElevation(directory, false);
+ }
+ }
+
+ if(theElevationLayer.valid())
+ {
+ theElevationLayer->sortByGsd();
+ }
+#endif
+}
+
+bool ossimPlanetTerrain::addElevation(const ossimFilename& file, bool sortFlag)
+{
+ osg::ref_ptr<ossimPlanetElevationDatabase> database = ossimPlanetElevationRegistry::instance()->openDatabase(file);
+ return addElevation(database.get(), sortFlag);
+}
+
+bool ossimPlanetTerrain::addElevation(osg::ref_ptr<ossimPlanetElevationDatabase> database, bool sortFlag)
+{
+ bool result = false;
+ if(database.valid()&&theElevationLayer.valid())
+ {
+ database->setGeoRefModel(theModel.get());
+ theElevationLayer->addBottom(database.get());
+ result = true;
+ if(sortFlag)
+ {
+ // make sure the highest accuracy is on top
+ theElevationLayer->sortByGsd();
+ }
+ }
+ return result;
+}
+
+void ossimPlanetTerrain::setNumberOfTextureLayers(ossim_uint32 size)
+{
+ TextureLayers temp = theTextureLayers;
+ theTextureLayers.resize(size);
+ ossim_uint32 idx = 0;
+ ossim_uint32 minBound = ossim::min(size, (ossim_uint32)temp.size());
+ for(idx = 0; idx < minBound;++idx)
+ {
+ theTextureLayers[idx] = temp[idx];
+ }
+ resetImageLayers();
+}
+
+bool ossimPlanetTerrain::setTextureLayer(ossim_uint32 idx,
+ ossimPlanetTextureLayer* layer)
+{
+ bool result = true;
+ if(idx < theTextureLayers.size())
+ {
+ if(theTextureLayers[idx].valid())
+ {
+ theTextureLayers[idx]->removeCallback(theTextureCallback.get());
+ }
+ theTextureLayers[idx] = layer;
+ if(layer)
+ {
+ layer->addCallback(theTextureCallback.get());
+ }
+ refreshImageLayers();
+ }
+ else if(idx == theTextureLayers.size())
+ {
+ theTextureLayers.push_back(layer);
+ if(layer)
+ {
+ layer->addCallback(theTextureCallback.get());
+ }
+ refreshImageLayers();
+ }
+ else
+ {
+ result = false;
+ }
+
+ return result;
+}
+
+ossim_uint32 ossimPlanetTerrain::numberOfTextureLayers()const
+{
+ return theTextureLayers.size();
+}
+
+ossimPlanetTextureLayer* ossimPlanetTerrain::textureLayer(ossim_uint32 idx)
+{
+ if(idx < theTextureLayers.size())
+ {
+ return theTextureLayers[idx].get();
+ }
+
+ return 0;
+}
+
+ossimPlanetElevationDatabaseGroup* ossimPlanetTerrain::elevationLayer()
+{
+ return theElevationLayer.get();
+}
+
+const ossimPlanetElevationDatabaseGroup* ossimPlanetTerrain::elevationLayer()const
+{
+ return theElevationLayer.get();
+}
+
+void ossimPlanetTerrain::traverse(osg::NodeVisitor &nv)
+{
+ // first mark any tile for refresh
+
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theElevationCache.valid()&&theElevationCache->exceedsMaxCacheSize())
+ {
+ if(theElevationCacheShrinkOperation->referenceCount() == 1)
+ {
+ theElevationCacheShrinkOperation->reset();
+ theElevationCacheShrinkOperation->setCache(theElevationCache.get());
+ theCacheShrinkThreadQueue->add(theElevationCacheShrinkOperation.get());
+ }
+ }
+ }
+// osgUtil::IntersectionVisitor* iv = dynamic_cast<osgUtil::IntersectionVisitor*>(&nv);
+// if(iv)
+// {
+// iv->setUseKdTreeWhenAvailable(true);
+// }
+// osg::Timer_t tick = osg::Timer::instance()->tick();
+ int savedCullSettings = 0;
+ // int savedCullMask = 0;
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if(cv)
+ {
+ // savedCullMask = cv->getCurrentCullingSet().getCullingMask();
+ savedCullSettings = cv->getCullingMode();
+ cv->getCurrentCullingSet().setCullingMask((osg::CullingSet::MaskValues)theCullSettings);
+ cv->setCullingMode(theCullSettings);
+ }
+ // bool frameNumberChanged = false;
+
+ if(nv.getFrameStamp())
+ {
+ // frameNumberChanged = nv.getFrameStamp()->getFrameNumber() != theLastFrameNumber;
+ theLastFrameNumber = nv.getFrameStamp()->getFrameNumber();
+ }
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::EVENT_VISITOR:
+ {
+ return;
+ }
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ refreshExtents();
+ theTextureQueue->setCurrentFrameNumber(theLastFrameNumber);
+ theElevationQueue->setCurrentFrameNumber(theLastFrameNumber);
+ theSplitQueue->setCurrentFrameNumber(theLastFrameNumber);
+ theMergeQueue->setCurrentFrameNumber(theLastFrameNumber);
+ theTextureQueue->operationQueue()->removeStoppedOperations();
+ theElevationQueue->operationQueue()->removeStoppedOperations();
+
+ // osg::Timer_t startTick = osg::Timer::instance()->tick();
+ // double delta =0.0;
+ if(resetRootsFlag())
+ {
+ buildRoot();
+ }
+
+ bool needToRedraw = (!theTextureQueue->empty()||
+ !theElevationQueue->empty()||
+ !theSplitQueue->empty());
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToApplyToGraphQueueMutex);
+ if(!theReadyToApplyToGraphQueue.empty()||
+ !theReadyToApplyToGraphNewNodesQueue.empty())
+ {
+ needToRedraw = true;
+ }
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNeedToCompileQueueMutex);
+ if(!theNeedToCompileQueue.empty())
+ {
+ needToRedraw = true;
+ }
+ }
+ if(needToRedraw)
+ {
+ setRedrawFlag(true); // request a new frame if not empty
+ }
+ pruneNeedToCompileAndAddToGraphThreadQueues();
+ removeTerrainChildren();
+ if(nv.getFrameStamp()&&(nv.getFrameStamp()->getFrameNumber()!=theLastApplyToGraphFrameNumber))
+ {
+ applyRequestsToGraph(1.25);
+ theLastApplyToGraphFrameNumber = nv.getFrameStamp()->getFrameNumber();
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+#if 0
+ ossim_uint32 idx = 0;
+ CountVisitor count;
+ for(idx = 0; idx < getNumChildren(); ++idx)
+ {
+ getChild(idx)->accept(count);
+ }
+ std::cout << "CULL COUNT ===== " << coun std::cout << "NODE COUNT ===== " << count.theNodeCount << std::endl;
+t.theCullCount << std::endl;
+#endif
+ ossimPlanetLayer::traverse(nv);
+ if(cv)
+ {
+ cv->getCurrentCullingSet().setCullingMask((osg::CullingSet::MaskValues) savedCullSettings);
+ cv->setCullingMode( (osg::CullSettings::CullingModeValues) savedCullSettings);
+ }
+ //std::cout << "f = " << theCurrentFrameNumber << std::endl;
+ if((nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR))
+ {
+
+ RemoveChildrenFromGraphVisitor visitor(this, nv.getFrameStamp()->getFrameNumber());
+ ossim_uint32 idx = 0;
+ ossim_uint32 maxIdx = getNumChildren();
+ for(idx = 0; idx < maxIdx; ++idx)
+ {
+ getChild(idx)->accept(visitor);
+ }
+ }
+}
+
+void ossimPlanetTerrain::setGrid(ossimPlanetGrid* grid)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+
+ theResetRootsFlag = true;
+ theGrid = grid;
+}
+
+const ossimPlanetGrid* ossimPlanetTerrain::grid()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theGrid.get();
+}
+
+ossimPlanetGrid* ossimPlanetTerrain::grid()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theGrid.get();
+}
+
+void ossimPlanetTerrain::removeTerrainTileFromGraph(ossimPlanetTerrainTile* tile)
+{
+ removeTerrainChildren(tile);
+}
+
+void ossimPlanetTerrain::removeTerrainChildren(ossimPlanetTerrainTile* tile)
+{
+ if(tile)
+ {
+ theChildrenToRemoveMutex.lock();
+ osg::ref_ptr<ossimPlanetTerrainTile> currentTile = tile;
+ // flatten graph to a single list of children
+ //
+ std::queue<osg::ref_ptr<ossimPlanetTerrainTile> > tiles;
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < currentTile->getNumChildren(); ++idx)
+ {
+ tiles.push((ossimPlanetTerrainTile*)currentTile->getChild(idx));
+ }
+ currentTile->removeChildren(0, currentTile->getNumChildren());
+ // now let's flatten the graph out and add to the remove tile list
+ //
+ while(!tiles.empty())
+ {
+ currentTile = tiles.front().get();
+ currentTile->cancelAllOperations();
+ tiles.pop();
+ //currentTile->setState(ossimPlanetTerrainTile::NEED_MERGING);
+ theChildrenToRemove.push_back(currentTile.get());
+ for(idx = 0; idx < currentTile->getNumChildren(); ++idx)
+ {
+ tiles.push((ossimPlanetTerrainTile*)currentTile->getChild(idx));
+ }
+ currentTile->removeChildren(0, currentTile->getNumChildren());
+ }
+ theChildrenToRemoveMutex.unlock();
+ }
+}
+
+void ossimPlanetTerrain::requestSplit(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ ossimPlanetOperation* request)
+{
+ if(theResetRootsFlag) return;
+ ossimPlanetTileRequest* tileRequest = dynamic_cast<ossimPlanetTileRequest*>(request);
+ if(tileRequest)
+ {
+ if(tileRequest->referenceCount() == 1)
+ {
+ tileRequest->setState(ossimPlanetOperation::READY_STATE);
+ tileRequest->setTimestampFirstRequest(framestamp->getReferenceTime());
+ tileRequest->setTile(tile);
+ theSplitQueue->add(tileRequest);
+ }
+ tileRequest->setPriority(priority);
+ tileRequest->setFrameNumberOfLastRequest(framestamp->getFrameNumber());
+ tileRequest->setTimestampLastRequest(framestamp->getReferenceTime());
+ }
+}
+
+void ossimPlanetTerrain::requestMerge(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ ossimPlanetOperation* request)
+{
+ ossimPlanetTileRequest* tileRequest = dynamic_cast<ossimPlanetTileRequest*>(request);
+ if(tileRequest)
+ {
+ tileRequest->reset();
+ tileRequest->setTile(tile);
+ tileRequest->setPriority(priority);
+ tileRequest->setFrameNumberOfLastRequest(framestamp->getFrameNumber());
+ theMergeQueue->add(tileRequest);
+ }
+
+}
+
+void ossimPlanetTerrain::requestTexture(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ const std::vector<ossim_uint32>& indices,
+ ossimPlanetOperation* request)
+{
+ if(theResetRootsFlag) return;
+ ossimPlanetTextureRequest* tileRequest = dynamic_cast<ossimPlanetTextureRequest*>(request);
+ if(tileRequest)
+ {
+ if(tileRequest->referenceCount() == 1)
+ {
+ tileRequest->reset();
+ tileRequest->setTimestampFirstRequest(framestamp->getReferenceTime());
+ tileRequest->setTile(tile);
+ tileRequest->setTextureLayerIndices(indices);
+ theTextureQueue->add(tileRequest);
+ }
+ tileRequest->setPriority(priority);
+ tileRequest->setFrameNumberOfLastRequest(framestamp->getFrameNumber());
+ tileRequest->setTimestampLastRequest(framestamp->getReferenceTime());
+ }
+}
+
+void ossimPlanetTerrain::requestElevation(ossimPlanetTerrainTile* tile,
+ ossim_float64 priority,
+ const osg::FrameStamp* framestamp,
+ ossimPlanetOperation* request)
+{
+ if(theResetRootsFlag) return;
+ ossimPlanetTileRequest* tileRequest = dynamic_cast<ossimPlanetTileRequest*>(request);
+ if(tileRequest)
+ {
+ if(tileRequest->referenceCount() == 1)
+ {
+ tileRequest->reset();
+ tileRequest->setTile(tile);
+ tileRequest->setTimestampFirstRequest(framestamp->getReferenceTime());
+ theElevationQueue->add(tileRequest);
+ }
+ tileRequest->setPriority(priority);
+ tileRequest->setFrameNumberOfLastRequest(framestamp->getFrameNumber());
+ tileRequest->setTimestampLastRequest(framestamp->getReferenceTime());
+ }
+}
+
+void ossimPlanetTerrain::compileGLObjects(osg::State& state, double compileTime)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNeedToCompileQueueMutex);
+ osg::Timer_t startT = osg::Timer::instance()->tick();
+ double delta = 0.0;
+ double deltaNextTest = 0.0;
+ double diff = 0.0;
+ bool done = theNeedToCompileQueue.empty();
+ if(!done)
+ {
+ setRedrawFlag(true);
+ }
+ osg::RenderInfo renderInfo;
+ renderInfo.setState(&state);
+ while(!done)
+ {
+ // returns false if no more objects in the request need compiling
+ if(theNeedToCompileQueue.front()->compileObjects(renderInfo, compileTime))
+ {
+ addRequestToReadyToApplyQueue(theNeedToCompileQueue.front().get());
+ theNeedToCompileQueue.pop_front();
+ }
+ osg::Timer_t testT = osg::Timer::instance()->tick();
+ delta = osg::Timer::instance()->delta_s(startT, testT);
+ diff = delta - deltaNextTest;
+ if((delta > (compileTime-diff))||
+ theNeedToCompileQueue.empty())
+ {
+ done = true;
+ }
+ deltaNextTest = delta;
+ }
+}
+
+bool ossimPlanetTerrain::resetRootsFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theResetRootsFlag;
+}
+
+void ossimPlanetTerrain::buildRoot()
+{
+ if(!theGrid.valid()) return;
+
+ theReadyToApplyToGraphQueue.clear();
+ theReadyToApplyToGraphNewNodesQueue.clear();
+ theNeedToCompileQueue.clear();
+ theSplitQueue->removeAllOperations();
+ theElevationQueue->removeAllOperations();
+ theTextureQueue->removeAllOperations();
+ bool hasActiveOperations = false;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMutex);
+ TileSet::iterator iter = theTileSet.begin();
+ while(iter != theTileSet.end())
+ {
+ (*iter)->cancelAllOperations();
+ if((*iter)->hasActiveOperations())
+ {
+ hasActiveOperations = true;
+ }
+ ++iter;
+ }
+ if(!hasActiveOperations)
+ {
+ theTileSet.clear();
+ removeChildren(0, getNumChildren());
+ }
+ }
+ if(!hasActiveOperations)
+ {
+ ossimPlanetGrid::TileIds rootIds;
+ theGrid->getRootIds(rootIds);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < rootIds.size(); ++idx)
+ {
+ ossimPlanetTerrainTile* tile = new ossimPlanetTerrainTile(rootIds[idx]);
+ tile->setTerrain(this);
+ tile->init();
+ addChild(tile);
+ }
+ theResetRootsFlag = false;
+ setRedrawFlag(true);
+ }
+}
+
+ossimPlanetTerrain* ossimPlanetTerrain::findTerrain(osg::NodePath& currentNodePath)
+{
+ if(currentNodePath.empty())
+ {
+ return 0;
+ }
+ for(osg::NodePath::reverse_iterator itr = currentNodePath.rbegin();
+ itr != currentNodePath.rend();
+ ++itr)
+ {
+ ossimPlanetTerrain* ts = dynamic_cast<ossimPlanetTerrain*>(*itr);
+ if (ts)
+ {
+ return ts;
+ }
+ }
+
+ return 0;
+}
+
+double ossimPlanetTerrain::maxTimeToSplit()const
+{
+ return theMaxTimeToSplit;
+}
+
+double ossimPlanetTerrain::maxTimeToMerge()const
+{
+ return theMaxTimeToMerge;
+}
+void ossimPlanetTerrain::registerTile(ossimPlanetTerrainTile* tile)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMutex);
+ if(tile)
+ {
+ theTileSet.insert(tile);
+ }
+ }
+}
+
+void ossimPlanetTerrain::unregisterTile(ossimPlanetTerrainTile* tile)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMutex);
+ TileSet::iterator iter = theTileSet.find(tile);
+ if(iter != theTileSet.end())
+ {
+ theTileSet.erase(iter);
+ }
+ }
+}
+ossimPlanetTerrainTile* ossimPlanetTerrain::findTile(const ossimPlanetTerrainTileId& id)
+{
+#if 0
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMapMutex);
+ TileSetMap::iterator iter = theTileSetMap.find(id);
+ if(iter != theTileSetMap.end())
+ {
+ return iter->second;
+ }
+#endif
+ return 0;
+}
+const ossimPlanetTerrainTile* ossimPlanetTerrain::findTile(const ossimPlanetTerrainTileId& id)const
+{
+#if 0
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMapMutex);
+ TileSetMap::const_iterator iter = theTileSetMap.find(id);
+ if(iter != theTileSetMap.end())
+ {
+ return iter->second;
+ }
+#endif
+ return 0;
+}
+
+void ossimPlanetTerrain::refreshImageAndElevationLayers(ossimPlanetExtents* extents)
+{
+ refreshImageLayers(extents);
+ refreshElevationLayers(extents);
+#if 0
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMutex);
+ TileSet::iterator iter = theTileSet.begin();
+ bool imageIntersects = true;
+ bool elevationIntersects = true;
+ osg::ref_ptr<ossimPlanetExtents> imageExtent = new ossimPlanetExtents;
+ osg::ref_ptr<ossimPlanetExtents> elevExtent = new ossimPlanetExtents;
+ ossim_uint32 idx;
+ while(iter != theTileSet.end())
+ {
+ ossim_uint32 bound = (*iter)->numberOfImageLayers();
+ if(extents)
+ {
+ theGrid->convertToGeographicExtents((*iter)->tileId(),
+ *imageExtent,
+ textureTileWidth(),
+ textureTileHeight());
+ theGrid->convertToGeographicExtents((*iter)->tileId(),
+ *elevExtent,
+ elevationTileWidth(),
+ elevationTileHeight());
+
+ if(extents->intersectsLatLon(*imageExtent.get())&&
+ extents->intersectsScale(*imageExtent.get()))
+ {
+ imageIntersects = true;
+ }
+ else
+ {
+ imageIntersects = false;
+ }
+
+ if(extents->intersectsLatLon(*elevExtent.get()))
+ {
+ elevationIntersects = true;
+ }
+ else
+ {
+ elevationIntersects = false;
+ }
+ }
+ if(elevationIntersects)
+ {
+ (*iter)->elevationLayer()->setRefreshFlag(true);
+ (*iter)->elevationLayer()->setNoMoreDataFlag(false);
+ }
+
+ if(imageIntersects)
+ {
+ for(idx = 0; idx < bound; ++idx)
+ {
+ (*iter)->imageLayer(idx)->setRefreshFlag(true);
+ (*iter)->imageLayer(idx)->setNoMoreDataFlag(false);
+ if(textureLayer(idx)&&((*iter)->tileId().level()>0))
+ {
+ bool hasDataFlag = textureLayer(idx)->hasTexture(textureTileWidth(),
+ textureTileHeight(),
+ (*iter)->tileId(),
+ *grid());
+ (*iter)->imageLayer(idx)->setNoMoreDataFlag(!hasDataFlag);
+ }
+ }
+ }
+ ++iter;
+ }
+ setRedrawFlag(true);
+#endif
+}
+
+void ossimPlanetTerrain::refreshImageLayers(ossimPlanetExtents* extents)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRefreshExtentsMutex);
+ if(theRefreshImageExtent.valid())
+ {
+ if(extents)
+ {
+ theRefreshImageExtent->combine(extents);
+ }
+ }
+ else if(extents)
+ {
+ theRefreshImageExtent = new ossimPlanetExtents(*extents);
+ }
+ else
+ {
+ theRefreshImageExtent = new ossimPlanetExtents();
+ }
+ setRedrawFlag(true);
+}
+
+void ossimPlanetTerrain::refreshElevationLayers(ossimPlanetExtents* extents)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRefreshExtentsMutex);
+ if(theRefreshElevationExtent.valid())
+ {
+ if(extents)
+ {
+ theRefreshElevationExtent->combine(extents);
+ }
+ }
+ else if(extents)
+ {
+ theRefreshElevationExtent = new ossimPlanetExtents(*extents);
+ }
+ else
+ {
+ theRefreshElevationExtent = new ossimPlanetExtents();
+ }
+ setRedrawFlag(true);
+}
+
+
+void ossimPlanetTerrain::refreshExtents()
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theRefreshExtentsMutex);
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(theTileSetMutex);
+ if(!theRefreshElevationExtent.valid()&&
+ !theRefreshImageExtent.valid())
+ {
+ return;
+ }
+ ossim_uint32 idx = 0;
+ TileSet::iterator iter = theTileSet.begin();
+ osg::ref_ptr<ossimPlanetExtents> tileExtent = new ossimPlanetExtents;
+ while(iter != theTileSet.end())
+ {
+ theGrid->convertToGeographicExtents((*iter)->tileId(),
+ *tileExtent,
+ textureTileWidth(),
+ textureTileHeight());
+ if(theRefreshImageExtent.valid())
+ {
+ if(theRefreshImageExtent->intersectsLatLon(*tileExtent.get()))//&&
+// theRefreshImageExtent->intersectsScale(*tileExtent.get()))
+ {
+ (*iter)->textureRequest()->cancel();
+ ossim_uint32 bound = (*iter)->numberOfImageLayers();
+ for(idx = 0; idx < bound; ++idx)
+ {
+ (*iter)->imageLayer(idx)->setRefreshFlag(true);
+ (*iter)->imageLayer(idx)->setNoMoreDataFlag(false);
+ if(textureLayer(idx)&&((*iter)->tileId().level()>0))
+ {
+ bool hasDataFlag = textureLayer(idx)->hasTexture(textureTileWidth(),
+ textureTileHeight(),
+ (*iter)->tileId(),
+ *grid());
+ (*iter)->imageLayer(idx)->setNoMoreDataFlag(!hasDataFlag);
+ }
+ }
+ }
+ }
+ if(theRefreshElevationExtent.valid())
+ {
+ if(theRefreshElevationExtent->intersectsLatLon(*tileExtent.get()))
+ {
+ (*iter)->elevationRequest()->cancel();
+ (*iter)->elevationLayer()->setRefreshFlag(true);
+ (*iter)->elevationLayer()->setNoMoreDataFlag(false);
+ if(elevationLayer()&&((*iter)->tileId().level()>0))
+ {
+#if 0
+ bool hasDataFlag = elevationLayer()->hasTexture(elevationTileWidth(),
+ elevationTileHeight(),
+ (*iter)->tileId(),
+ *grid());
+ (*iter)->elevationLayer()->setNoMoreDataFlag(!hasDataFlag);
+#else
+ (*iter)->elevationLayer()->setNoMoreDataFlag(false);
+#endif
+ }
+ }
+ }
+
+ ++iter;
+ }
+
+ theRefreshElevationExtent = 0;
+ theRefreshImageExtent = 0;
+ }
+ setRedrawFlag(true);
+}
+
+void ossimPlanetTerrain::resetImageLayers()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTileSetMutex);
+ TileSet::iterator iter = theTileSet.begin();
+ while(iter != theTileSet.end())
+ {
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = (*iter)->numberOfImageLayers();
+ for(idx = 0; idx < bound; ++idx)
+ {
+ (*iter)->resetImageLayers();
+ }
+ ++iter;
+ }
+ setRedrawFlag(true);
+}
+
+void ossimPlanetTerrain::resetGraph()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theResetRootsFlag = true;
+}
+
+void ossimPlanetTerrain::setModel(ossimPlanetGeoRefModel* model)
+{
+ ossimPlanetLayer::setModel(model);
+ if(theElevationLayer.valid())
+ {
+ theElevationLayer->setGeoRefModel(model);
+ }
+}
+
+void ossimPlanetTerrain::addRequestToReadyToApplyQueue(ossimPlanetTileRequest* request)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToApplyToGraphQueueMutex);
+ if(dynamic_cast<ossimPlanetSplitRequest*>(request))
+ {
+ theReadyToApplyToGraphNewNodesQueue.push_back(request);
+ }
+ else
+ {
+ theReadyToApplyToGraphQueue.push_back(request);
+ }
+ setRedrawFlag(true);
+}
+
+void ossimPlanetTerrain::addRequestToNeedToCompileQueue(ossimPlanetTileRequest* request)
+{
+ if(thePager.valid())
+ {
+
+ osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet = new osgUtil::IncrementalCompileOperation::CompileSet();
+ osgUtil::IncrementalCompileOperation* compileOperation = thePager->getIncrementalCompileOperation();
+ if(compileOperation&&!compileOperation->getContextSet().empty())
+ {
+ //osgUtil::StateToCompile stateToCompile(osgUtil::GLObjectsVisitor::COMPILE_DISPLAY_LISTS|osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES);
+ //compileSet->buildCompileMap(compileOperation->getContextSet());
+ request->populateCompileSet(compileOperation->getContextSet(), *compileSet.get());
+ compileSet->_compileCompletedCallback = new ossimPlanetDatabasePagerCompileCompletedCallback(this, request);
+ compileOperation->add(compileSet.get(), false);
+ }
+ else
+ {
+ addRequestToReadyToApplyQueue(request);
+ }
+ //std::cout << compileOperation << std::endl;
+
+ }
+ }
+
+void ossimPlanetTerrain::applyRequestsToGraph(double maxTime)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToApplyToGraphQueueMutex);
+ if(theReadyToApplyToGraphQueue.empty()&&theReadyToApplyToGraphNewNodesQueue.empty()) return;
+ osg::ref_ptr<ossimPlanetTileRequest> request;
+ bool doneFlag = false;
+ ossim_uint32 operationCount = 0;
+ osg::Timer_t startTick = osg::Timer::instance()->tick();
+ while(!doneFlag)
+ {
+ if(!theReadyToApplyToGraphQueue.empty())
+ {
+ // theReadyToApplyToGraphQueue.sort(ossimPlanetTileRequest::SortFunctor());
+ if((*theReadyToApplyToGraphQueue.begin())->isRequestCurrent(theTextureQueue->currentFrameNumber()))
+ {
+ (*theReadyToApplyToGraphQueue.begin())->applyToGraph();
+ ++operationCount;
+ theReadyToApplyToGraphQueue.pop_front();
+ }
+ else
+ {
+ theReadyToApplyToGraphQueue.pop_front();
+ }
+ }
+#if 1
+ if(!theReadyToApplyToGraphNewNodesQueue.empty())
+ {
+ //theReadyToApplyToGraphNewNodesQueue.sort(ossimPlanetTileRequest::SortFunctor());
+ if((*theReadyToApplyToGraphNewNodesQueue.begin())->isRequestCurrent(theTextureQueue->currentFrameNumber()))
+ {
+ (*theReadyToApplyToGraphNewNodesQueue.begin())->applyToGraph();
+ ++operationCount;
+ theReadyToApplyToGraphNewNodesQueue.pop_front();
+ }
+ else
+ {
+ theReadyToApplyToGraphNewNodesQueue.pop_front();
+ }
+ }
+#endif
+ double delta = osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick());
+#if 1
+ doneFlag = ((theReadyToApplyToGraphQueue.empty()&&theReadyToApplyToGraphNewNodesQueue.empty())||
+ (delta > maxTime)||
+ (operationCount>=theMaxNumberOfOperationsToApplyToGraphPerFrame));
+#else
+ doneFlag = ((theReadyToApplyToGraphQueue.empty())||
+ (delta > maxTime)||
+ (operationCount>=theMaxNumberOfOperationsToApplyToGraphPerFrame));
+#endif
+ }
+ setRedrawFlag(true);
+}
+
+
+void ossimPlanetTerrain::pruneNeedToCompileAndAddToGraphThreadQueues()
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToApplyToGraphQueueMutex);
+ ossimPlanetTileRequest::List::iterator iter = theReadyToApplyToGraphQueue.begin();
+ while(iter != theReadyToApplyToGraphQueue.end())
+ {
+ if(((*iter)->state() == ossimPlanetOperation::CANCELED_STATE)||
+ (!(*iter)->isRequestCurrent(theTextureQueue->currentFrameNumber())))
+ {
+ iter = theReadyToApplyToGraphQueue.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+#if 1
+ {
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theReadyToApplyToGraphQueueMutex);
+ ossimPlanetTileRequest::List::iterator iter = theReadyToApplyToGraphNewNodesQueue.begin();
+ while(iter != theReadyToApplyToGraphNewNodesQueue.end())
+ {
+ if(((*iter)->state() == ossimPlanetOperation::CANCELED_STATE)||
+ (!(*iter)->isRequestCurrent(theTextureQueue->currentFrameNumber())))
+ {
+ iter = theReadyToApplyToGraphNewNodesQueue.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+#endif
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theNeedToCompileQueueMutex);
+ ossimPlanetTileRequest::List::iterator iter = theNeedToCompileQueue.begin();
+ while(iter != theNeedToCompileQueue.end())
+ {
+ if(((*iter)->state() == ossimPlanetOperation::CANCELED_STATE)||
+ (!(*iter)->isRequestCurrent(theTextureQueue->currentFrameNumber())))
+ {
+ iter = theNeedToCompileQueue.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+}
+
+void ossimPlanetTerrain::removeTerrainChildren(double maxTime)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenToRemoveMutex);
+ osg::Timer_t startTick = osg::Timer::instance()->tick();
+ // osgUtil::GLObjectsVisitor visitor(osgUtil::GLObjectsVisitor::RELEASE_DISPLAY_LISTS|
+ // osgUtil::GLObjectsVisitor::RELEASE_STATE_ATTRIBUTES);
+ RemoveChildrenList::iterator iter = theChildrenToRemove.begin();
+ while(iter!=theChildrenToRemove.end())
+ {
+ if((*iter)->hasActiveOperations())
+ {
+ (*iter)->cancelAllOperations();
+ ++iter;
+ }
+ else
+ {
+ (*iter)->releaseGLObjects();
+ iter = theChildrenToRemove.erase(iter);
+ }
+ double delta = osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick());
+ if(delta > maxTime)
+ {
+ break;
+ }
+ }
+ if(theChildrenToRemove.size()>0)
+ {
+ iter = theChildrenToRemove.begin();
+ //std::cout << "_____________" << std::endl;
+ while(iter!=theChildrenToRemove.end())
+ {
+ //std::cout << (*iter)->tileId() << std::endl;
+ // std::cout << "elevationRequest = " << (*iter)->elevationRequest()->referenceCount() << std::endl;
+ // std::cout << "textureRequest = " << (*iter)->textureRequest()->referenceCount() << std::endl;
+ // std::cout << "splitRequest = " << (*iter)->splitRequest()->referenceCount() << std::endl;
+ ++iter;
+ }
+ //std::cout << "Elevation queue size = " << theElevationQueue->operationQueue()->size() << std::endl;
+ //std::cout << "List size = " << theChildrenToRemove.size() << std::endl;
+ }
+}
+
+void ossimPlanetTerrain::setMaxNumberOfOperationsToApplyToGraphPerFrame(ossim_uint32 value)
+{
+ theMaxNumberOfOperationsToApplyToGraphPerFrame = value;
+}
+
+void ossimPlanetTerrain::setCullAmountType(CullAmountType cullAmount)
+{
+ switch(cullAmount)
+ {
+ case NO_CULL:
+ {
+ theCullSettings = osg::CullSettings::NO_CULLING;
+ break;
+ }
+ case LOW_CULL:
+ {
+ theCullSettings = osg::CullSettings::SMALL_FEATURE_CULLING;
+ break;
+ }
+ case MEDIUM_LOW_CULL:
+ {
+ theCullSettings = static_cast<osg::CullSettings::CullingModeValues>(osg::CullSettings::SMALL_FEATURE_CULLING|
+ osg::CullSettings::CLUSTER_CULLING);
+ break;
+ }
+ case MEDIUM_CULL:
+ {
+ theCullSettings = static_cast<osg::CullSettings::CullingModeValues>(osg::CullSettings::SMALL_FEATURE_CULLING|
+ osg::CullSettings::CLUSTER_CULLING|
+ osg::CullSettings::VIEW_FRUSTUM_SIDES_CULLING);
+ break;
+ }
+ case MEDIUM_HIGH_CULL:
+ {
+ theCullSettings = static_cast<osg::CullSettings::CullingModeValues>(osg::CullSettings::SMALL_FEATURE_CULLING|
+ osg::CullSettings::CLUSTER_CULLING|
+ osg::CullSettings::VIEW_FRUSTUM_CULLING);
+ break;
+ }
+ case HIGH_CULL:
+ {
+ theCullSettings = static_cast<osg::CullSettings::CullingModeValues>(osg::CullSettings::ENABLE_ALL_CULLING);
+ break;
+ }
+ }
+ setRedrawFlag(true);
+}
+void ossimPlanetTerrain::setTextureTileSize(ossim_uint32 width,
+ ossim_uint32 height)
+{
+ theTextureTileWidth = width;
+ theTextureTileHeight = height;
+}
+
+ossim_uint32 ossimPlanetTerrain::textureTileWidth()const
+{
+ return theTextureTileWidth;
+}
+
+ossim_uint32 ossimPlanetTerrain::textureTileHeight()const
+{
+ return theTextureTileHeight;
+}
+
+void ossimPlanetTerrain::setElevationTileSize(ossim_uint32 width,
+ ossim_uint32 height)
+{
+ theElevationTileWidth = width|1; // make sure that it's odd number
+ theElevationTileHeight = height|1; // make sure that it's an odd number
+}
+ossim_uint32 ossimPlanetTerrain::elevationTileWidth()const
+{
+ return theElevationTileWidth;
+}
+
+ossim_uint32 ossimPlanetTerrain::elevationTileHeight()const
+{
+ return theElevationTileHeight;
+}
+
+void ossimPlanetTerrain::setElevationDensityType(ElevationDensityType type)
+{
+ switch(type)
+ {
+ case LOW_ELEVATION_DENSITY:
+ {
+ setElevationTileSize(9, 9);
+ break;
+ }
+ case MEDIUM_LOW_ELEVATION_DENSITY:
+ {
+ setElevationTileSize(17, 17);
+ break;
+ }
+ case MEDIUM_ELEVATION_DENSITY:
+ {
+ setElevationTileSize(33, 33);
+ break;
+ }
+ case MEDIUM_HIGH_ELEVATION_DENSITY:
+ {
+ setElevationTileSize(65, 65);
+ break;
+ }
+ case HIGH_ELEVATION_DENSITY:
+ {
+ setElevationTileSize(129, 129);
+ break;
+ }
+ }
+ if(theElevationCache.valid())
+ {
+ theElevationCache->clean();
+ }
+}
+
+void ossimPlanetTerrain::setTextureDensityType(TextureDensityType type)
+{
+ switch(type)
+ {
+ case LOW_TEXTURE_DENSITY:
+ {
+ setTextureTileSize(64, 64);
+ break;
+ }
+ case MEDIUM_LOW_TEXTURE_DENSITY:
+ {
+ setTextureTileSize(128, 128);
+ break;
+ }
+ case MEDIUM_TEXTURE_DENSITY:
+ {
+ setTextureTileSize(256, 256);
+ break;
+ }
+ case MEDIUM_HIGH_TEXTURE_DENSITY:
+ {
+ setTextureTileSize(512, 512);
+ break;
+ }
+ case HIGH_TEXTURE_DENSITY:
+ {
+ setTextureTileSize(1024, 1024);
+ break;
+ }
+ }
+}
+
+ossimPlanetTerrain::ElevationDensityType ossimPlanetTerrain::elevationDensityType()const
+{
+ ossim_int32 size = ossim::max(elevationTileHeight(), elevationTileWidth());
+
+ if(size <=9)
+ {
+ return LOW_ELEVATION_DENSITY;
+ }
+ else if(size <=17)
+ {
+ return MEDIUM_LOW_ELEVATION_DENSITY;
+ }
+ else if(size <=33)
+ {
+ return MEDIUM_ELEVATION_DENSITY;
+ }
+ else if(size <=64)
+ {
+ return MEDIUM_HIGH_ELEVATION_DENSITY;
+ }
+
+ return HIGH_ELEVATION_DENSITY;
+}
+
+ossimPlanetTerrain::TextureDensityType ossimPlanetTerrain::textureDensityType()const
+{
+ ossim_int32 size = ossim::max(textureTileWidth(), textureTileHeight());
+
+ if(size <=64)
+ {
+ return LOW_TEXTURE_DENSITY;
+ }
+ else if(size <=128)
+ {
+ return MEDIUM_LOW_TEXTURE_DENSITY;
+ }
+ else if(size <=256)
+ {
+ return MEDIUM_TEXTURE_DENSITY;
+ }
+ else if(size <=512)
+ {
+ return MEDIUM_HIGH_TEXTURE_DENSITY;
+ }
+
+ return HIGH_TEXTURE_DENSITY;
+}
+
+void ossimPlanetTerrain::setSplitMergePixelMetricParameters(ossim_float64 mergeMetric,
+ ossim_float64 splitMetric)
+{
+ theSplitPixelMetric = splitMetric;
+ theMergePixelMetric = mergeMetric;
+}
+
+void ossimPlanetTerrain::setSplitMergeMetricType(SplitMergeMetricType type)
+{
+ theSplitMergeMetricType = type;
+}
+
+ossimPlanetTerrain::SplitMergeMetricType ossimPlanetTerrain::splitMergeMetricType()const
+{
+ return theSplitMergeMetricType;
+}
+
+ossim_float64 ossimPlanetTerrain::splitPixelMetric()const
+{
+ return theSplitPixelMetric;
+}
+
+ossim_float64 ossimPlanetTerrain::mergePixelMetric()const
+{
+ return theMergePixelMetric;
+
+}
+
+void ossimPlanetTerrain::setSplitMergeSpeedType(SplitMergeSpeedType type)
+{
+ switch(type)
+ {
+ case LOW_SPEED:
+ {
+ setSplitMergeLodScale(1.5);
+ theSplitPixelMetric = 16;
+ theMergePixelMetric = 8;
+ break;
+ }
+ case MEDIUM_LOW_SPEED:
+ {
+ setSplitMergeLodScale(3.0);
+ theSplitPixelMetric = 10;
+ theMergePixelMetric = 5;
+ break;
+ }
+ case MEDIUM_SPEED:
+ {
+ setSplitMergeLodScale(5.0);
+ theSplitPixelMetric = 8;
+ theMergePixelMetric = 4;
+ break;
+ }
+ case MEDIUM_HIGH_SPEED:
+ {
+ setSplitMergeLodScale(6.5);
+ theSplitPixelMetric = 6;
+ theMergePixelMetric = 3;
+ break;
+ }
+ case HIGH_SPEED:
+ {
+ setSplitMergeLodScale(8.0);
+ theSplitPixelMetric = 4;
+ theMergePixelMetric = 2;
+ break;
+ }
+ }
+}
+
+
+void ossimPlanetTerrain::setSplitMergeLodScale(ossim_float64 ratio)
+{
+ theSplitMergeLodScale = ratio;
+}
+
+ossim_float64 ossimPlanetTerrain::splitMergeLodScale()const
+{
+ return theSplitMergeLodScale;
+}
+
+void ossimPlanetTerrain::setElevationExaggeration(ossim_float64 exaggeration)
+{
+ theElevationExaggeration = exaggeration;
+}
+
+ossim_float64 ossimPlanetTerrain::elevationExaggeration()const
+{
+ return theElevationExaggeration;
+}
+
+void ossimPlanetTerrain::setMinimumTimeToCompilePerFrameInSeconds(double timeInSeconds)
+{
+ theMinimumTimeToCompilePerFrame = timeInSeconds;
+}
+
+ossim_float64 ossimPlanetTerrain::minimumTimeToCompilePerFrame()const
+{
+ return theMinimumTimeToCompilePerFrame;
+}
+
+void ossimPlanetTerrain::setPrecompileEnabledFlag(bool flag)
+{
+ thePrecompileEnabledFlag = flag;
+}
+
+bool ossimPlanetTerrain::precompileEnabledFlag()const
+{
+ return thePrecompileEnabledFlag;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainGeometryTechnique.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainGeometryTechnique.cpp
new file mode 100644
index 0000000..ddc49fd
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainGeometryTechnique.cpp
@@ -0,0 +1,1744 @@
+#include <ossimPlanet/ossimPlanetTerrainGeometryTechnique.h>
+#include <ossimPlanet/ossimPlanetTerrainTile.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetTexture2D.h>
+#include <ossimPlanet/ossimPlanet.h>
+#include <iostream>
+#include <osg/io_utils>
+#include <osg/Timer>
+#include <osg/CullFace>
+#include <osgDB/Registry>
+#include <osgUtil/SmoothingVisitor>
+#include <osgUtil/TriStripVisitor>
+#include <queue>
+#include <osgUtil/IntersectionVisitor>
+#include <osgUtil/Simplifier>
+
+void ossimPlanetTerrainGeometryTechnique::UpdateChildTextureVisitor::apply(osg::Node& node)
+{
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(&node);
+ if(tile)
+ {
+ ossimPlanetTerrainGeometryTechnique* technique = (ossimPlanetTerrainGeometryTechnique*)tile->terrainTechnique();
+ if(technique)
+ {
+ BufferData& buffer = technique->readOnlyBuffer();
+ if(buffer.theGeode.valid())
+ {
+ if(!tile->imageLayer(theIdx)->image()||
+ (tile->imageLayer(theIdx)->noMoreDataFlag()&&
+ tile->imageLayer(theIdx)->refreshFlag())) // no valid image then set to the best parent texture and keep going
+ {
+ osg::StateSet* stateset = buffer.theGeode->getOrCreateStateSet();
+ stateset->setTextureAttributeAndModes(theIdx, theTexture.get(), osg::StateAttribute::ON);
+ technique->updateTextureMatrix(stateset, theIdx, tile->tileId(), theTexture->tileId());
+ traverse(node);
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::CullNode::traverse(osg::NodeVisitor& nv)
+{
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ theCulledFlag = false;
+
+ if(!cv) return;
+ const osg::Vec3d& center = theBoundingBox->center();
+ double radius = theBoundingBox->radius();
+ thePixelSize = cv->clampedPixelSize(center, radius);
+ osg::Vec3d eye = cv->getEyeLocal();
+ osg::Vec3d eyeDirection = cv->getLookVectorLocal();
+ const osg::Polytope& frustum = cv->getCurrentCullingSet().getFrustum();
+ theEyeDistance = (eye-theBoundingBox->center()).length();
+ theEyeToVolumeDistance = (theEyeDistance - theBoundingBox->radius());
+ if(theEyeToVolumeDistance < theBoundingBox->radius()) theEyeToVolumeDistance = FLT_EPSILON;
+#if 1
+ // do cluster cull if enabled
+ //
+ if (cv->getCullingMode() & osg::CullSettings::CLUSTER_CULLING)
+ {
+ if(theClusterCullingDeviation >= -1.0)
+ {
+ // let's use the bounding box center instead of the cluster center
+ // seems to be more stable right now to do it this way.
+ //
+ //osg::Vec3d eyeCp = eye - center;
+ osg::Vec3d eyeCp = eye - theClusterCullingControlPoint;
+ double radius = eyeCp.length();
+
+ if (radius>=theClusterCullingRadius)
+ {
+ double deviation = (eyeCp * theClusterCullingNormal)/radius;
+
+ theCulledFlag = (deviation < theClusterCullingDeviation);
+ }
+ }
+ }
+#endif
+ theWithinFrustumFlag = true;
+ if(theBoundingBox->isInFront(eye, eyeDirection))
+ {
+ theWithinFrustumFlag = theBoundingBox->intersects(frustum);
+ }
+ else
+ {
+ theWithinFrustumFlag = false;
+ }
+
+ if((cv->getCullingMode()&osg::CullSettings::VIEW_FRUSTUM_CULLING)&&!theCulledFlag)
+ {
+ theCulledFlag = !theWithinFrustumFlag;
+ }
+}
+
+osg::BoundingSphere ossimPlanetTerrainGeometryTechnique::CullNode::computeBound() const
+{
+ osg::BoundingSphere bsphere(theBoundingBox->center(),
+ theBoundingBox->radius());
+ if (!bsphere.valid()) return bsphere;
+
+ // note, NULL pointer for NodeVisitor, so compute's need
+ // to handle this case gracefully, normally this should not be a problem.
+ osg::Matrix l2w;
+
+ computeLocalToWorldMatrix(l2w,NULL);
+
+ osg::Vec3d xdash = bsphere._center;
+ xdash.x() += bsphere._radius;
+ xdash = xdash*l2w;
+
+ osg::Vec3d ydash = bsphere._center;
+ ydash.y() += bsphere._radius;
+ ydash = ydash*l2w;
+
+ osg::Vec3d zdash = bsphere._center;
+ zdash.z() += bsphere._radius;
+ zdash = zdash*l2w;
+
+
+ bsphere._center = bsphere._center*l2w;
+
+ xdash -= bsphere._center;
+ double len_xdash = xdash.length();
+
+ ydash -= bsphere._center;
+ double len_ydash = ydash.length();
+
+ zdash -= bsphere._center;
+ double len_zdash = zdash.length();
+
+ bsphere._radius = len_xdash;
+ if (bsphere._radius<len_ydash) bsphere._radius = len_ydash;
+ if (bsphere._radius<len_zdash) bsphere._radius = len_zdash;
+
+ return bsphere;
+
+}
+
+ossimPlanetTerrainGeometryTechnique::ossimPlanetTerrainGeometryTechnique()
+:ossimPlanetTerrainTechnique()
+{
+}
+
+ossimPlanetTerrainGeometryTechnique::ossimPlanetTerrainGeometryTechnique(const ossimPlanetTerrainGeometryTechnique& src,
+ const osg::CopyOp& copyop)
+:ossimPlanetTerrainTechnique(src, copyop)
+{
+}
+
+ossimPlanetTerrainGeometryTechnique::~ossimPlanetTerrainGeometryTechnique()
+{
+ BufferData& buffer = readOnlyBuffer();
+ buffer.theTransform = 0;
+ buffer.theGeode = 0;
+ buffer.theGeometry = 0;
+ buffer.theClusterCullingCallback = 0;
+ buffer.theCullNode = 0;
+
+ buffer = writeBuffer();
+ buffer.theTransform = 0;
+ buffer.theGeode = 0;
+ buffer.theGeometry = 0;
+ buffer.theClusterCullingCallback = 0;
+ buffer.theCullNode = 0;
+}
+
+void ossimPlanetTerrainGeometryTechnique::setTerrainTile(ossimPlanetTerrainTile* tile)
+{
+ if(tile)
+ {
+ tile->setCullingActive(false);
+ }
+ ossimPlanetTerrainTechnique::setTerrainTile(tile);
+}
+
+void ossimPlanetTerrainGeometryTechnique::swapBuffers()
+{
+ //std::swap(theCurrentReadOnlyBuffer,theCurrentWriteBuffer);
+}
+
+void ossimPlanetTerrainGeometryTechnique::update(osgUtil::UpdateVisitor* uv)
+{
+ BufferData& buffer = readOnlyBuffer();
+ if (theTerrainTile)
+ {
+ updateRequests(*uv);
+ // let's immediately initialize a level 0 tile
+ //
+ if(theTerrainTile->tileId().level() == 0)
+ {
+ if(!readOnlyBuffer().theGeometry.valid())
+ {
+ theTerrainTile->init();
+ }
+ }
+ if(buffer.theTransform.valid())
+ {
+ buffer.theTransform->accept(*uv);
+ }
+ theTerrainTile->osg::Group::traverse(*uv);
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::cull(osgUtil::CullVisitor* cv)
+{
+ BufferData& buffer = readOnlyBuffer();
+
+ if(isCulled(buffer,cv))
+ {
+ return;
+ }
+ theTerrainTile->updateFrameAndTimeStamps(cv->getFrameStamp());
+ thePriorityPoint = cv->getEyeLocal();
+ theAdjustedEye = cv->getEyeLocal();
+
+ if(theTerrainTile->terrain())
+ {
+ if(theTerrainTile->terrain()->falseEyeFlag())
+ {
+ theAdjustedEye = theTerrainTile->terrain()->falseEye();
+ thePriorityPoint = theAdjustedEye;
+ }
+ else if(theTerrainTile->terrain()->priorityPointFlag())
+ {
+ thePriorityPoint = theTerrainTile->terrain()->priorityPoint();
+ }
+ }
+
+ bool addChildren = false;
+ bool removeChildren = false;
+
+ if(theTerrainTile->terrain()->splitMergeMetricType() == ossimPlanetTerrain::DISTANCE_METRIC)
+ {
+ double splitMergeLodScale = theTerrainTile->terrain()->splitMergeLodScale();
+ double ratio = splitMergeLodScale*thePatchBound.radius();
+ double distance = (theAdjustedEye - thePatchBound.center()).length();
+ removeChildren = distance > ratio;
+ addChildren = (distance < ratio)&&isLeaf();
+ }
+ else
+ {
+ osg::Vec2d deltaXY;
+ theTerrainTile->terrain()->grid()->widthHeightInModelSpace(theTerrainTile->tileId(), deltaXY);
+ //ossim_float64 maxSize =.5*(deltaXY[0] + deltaXY[1]);
+ ossim_float64 maxSize =ossim::min(deltaXY[0], deltaXY[1]);
+ ossim_float64 averageMeters = ossimGpt().metersPerDegree().y* sqrt(2.0*maxSize*maxSize);
+ ossim_float64 averageRadius = averageMeters*theTerrainTile->terrain()->model()->getInvNormalizationScale();
+ ossim_float64 pixelSize = cv->clampedPixelSize(thePatchBound.center(), averageRadius);
+ ossim_float64 pixelWidth = ossim::max(theTerrainTile->terrain()->textureTileWidth(),
+ theTerrainTile->terrain()->textureTileHeight());
+ ossim_float64 mergeWidth = pixelWidth*theTerrainTile->terrain()->mergePixelMetric();
+ ossim_float64 splitWidth = pixelWidth*theTerrainTile->terrain()->splitPixelMetric();
+
+ if(pixelSize < mergeWidth)
+ {
+ removeChildren = true;
+ }
+ else if(pixelSize > splitWidth)
+ {
+ addChildren = isLeaf();
+ }
+ }
+ // we can only add children if the previous buffered cull setting are not culled for
+ // all child nodes and if we don't have all the children and if we are not culled
+ //
+ if(addChildren)
+ {
+ if(theTerrainTile->tileId().level() > 17)
+ {
+ addChildren = false;
+ }
+ else
+ {
+ theTerrainTile->terrain()->requestSplit(theTerrainTile,
+ splitPriority(),
+ cv->getFrameStamp(),
+ theTerrainTile->splitRequest());
+
+ }
+ }
+ if(isLeaf()||removeChildren)
+ {
+ if (buffer.theTransform.valid())
+ {
+ buffer.theTransform->accept(*cv);
+ }
+ }
+ else
+ {
+ theTerrainTile->osg::Group::traverse(*cv);
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::updateRequests(osg::NodeVisitor& nv)
+{
+ // ossimPlanetTerrainTile* parentTile = theTerrainTile->parentTile();
+ bool canRequest = true;
+ // we need to loop this and add requests for multi textures.
+ //
+ // if(isLeaf())
+ if(canRequest)
+ {
+ std::vector<ossim_uint32> textureIndices;
+ ossimPlanetTerrainTile* current = theTerrainTile;
+ // bool doneImage = false;
+ bool doneElevation = false;
+ if(current)
+ {
+ ossim_uint32 imageLayerCount = current->numberOfImageLayers();
+ ossim_uint32 imageLayerIdx = 0;
+ for(imageLayerIdx = 0; imageLayerIdx < imageLayerCount; ++imageLayerIdx)
+ {
+ ossimPlanetTerrainImageLayer* layer = current->imageLayer(imageLayerIdx);
+ if(layer&&
+ (!layer->noMoreDataFlag())&&
+ (!layer->image()||
+ (layer->image()->tileId().level() != current->tileId().level())||
+ (layer->refreshFlag())))
+ {
+ textureIndices.push_back(imageLayerIdx);
+ // doneImage = true;
+ }
+ }
+ if(textureIndices.size() > 0)
+ {
+ theTerrainTile->terrain()->requestTexture(current,
+ current->terrainTechnique()->texturePriority(),
+ nv.getFrameStamp(),
+ textureIndices,
+ current->textureRequest());
+ }
+ ossimPlanetTerrainImageLayer* elevLayer = current->elevationLayer();
+ if(!doneElevation&&
+ elevLayer&&
+ (!elevLayer->noMoreDataFlag())&&
+ (!elevLayer->image()||
+ (elevLayer->image()->tileId().level()!=current->tileId().level())||
+ (elevLayer->refreshFlag())))
+ {
+ theTerrainTile->terrain()->requestElevation(current,
+ current->terrainTechnique()->elevationPriority(),
+ nv.getFrameStamp(),
+ current->elevationRequest());
+ doneElevation = true;
+ }
+ }
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::traverse(osg::NodeVisitor& nv)
+{
+ // if app traversal update the frame count.
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv);
+ if (uv)
+ {
+ update(uv);
+ return;
+ }
+ break;
+ }
+ case osg::NodeVisitor::CULL_VISITOR:
+ {
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if (cv)
+ {
+ cull(cv);
+ return;
+ }
+ break;
+ }
+ default:
+ {
+ BufferData& buffer = readOnlyBuffer();
+ if(nv.getTraversalMode() == osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
+ {
+ if(isLeaf())
+ {
+ if(buffer.theTransform.valid())
+ {
+ buffer.theTransform->accept(nv);
+ }
+ return;
+ }
+ }
+ else
+ {
+ if(buffer.theTransform.valid())
+ {
+ buffer.theTransform->accept(nv);
+ }
+ }
+ break;
+ }
+ }
+ theTerrainTile->osg::Group::traverse(nv);
+}
+
+void averageNormal(osg::Vec3d& center,
+ osg::Vec3d& normal,
+ const osg::Vec3d& p0,
+ const osg::Vec3d& p1,
+ const osg::Vec3d& p2,
+ const osg::Vec3d& p3)
+{
+ center = (p0+p1+p2+p3)*.25;
+ osg::Vec3d delta1, delta2;
+ delta1 = (p0-center);
+ delta2 = (p1-center);
+ delta1.normalize();
+ delta2.normalize();
+ normal = delta1^delta2;
+ delta1 = (p1-center);
+ delta2 = (p2-center);
+ delta1.normalize();
+ delta2.normalize();
+ normal += (delta1^delta2);
+ delta1 = (p2-center);
+ delta2 = (p3-center);
+ delta1.normalize();
+ delta2.normalize();
+ normal += (delta1^delta2);
+ delta1 = (p3-center);
+ delta2 = (p0-center);
+ delta1.normalize();
+ delta2.normalize();
+ normal += (delta1^delta2);
+
+ normal.normalize();
+}
+
+void ossimPlanetTerrainGeometryTechnique::buildMesh(ossimPlanetTerrainTile* /* optionalParent */)
+{
+ if(!theModel.valid()||!theGrid.valid()||!theTerrainTile||!theTerrainTile->terrain()) return;
+ BufferData& buffer = writeBuffer();
+ osg::ref_ptr<ossimPlanetImage> elevationImage = theTerrainTile->elevationLayer()->image();
+ //ossim_float32* elevationData = 0;
+ ossim_float64 skirtScale = .08;
+ unsigned int numRows = theTerrainTile->terrain()->elevationTileHeight();
+ unsigned int numCols = theTerrainTile->terrain()->elevationTileWidth();
+ ossim_int32 padding = 0;
+ if(elevationImage.valid())
+ {
+ //elevationData = (ossim_float32*)elevationImage->data();
+ numCols = elevationImage->widthWithoutPadding();
+ numRows = elevationImage->heightWithoutPadding();
+ padding = elevationImage->padding();
+ }
+ //std::cout << "w,h,pad = " << numCols <<", " << numRows << ", " << padding << "\n";
+ buffer.theGeode = new osg::Geode;
+ buffer.theTransform = new osg::MatrixTransform;
+ buffer.theGeometry = new osg::Geometry;
+ buffer.theGeode->addDrawable(buffer.theGeometry.get());
+ buffer.theClusterCullingCallback = new osg::ClusterCullingCallback();
+ osg::Geometry* geometry = buffer.theGeometry.get();
+
+ buffer.theTransform->addChild(buffer.theGeode.get());
+ buffer.theGeode->addDrawable(buffer.theGeometry.get());
+
+
+ unsigned int numVerticesInBody = numCols*numRows;
+ unsigned int numVertices = numVerticesInBody;
+ ossimPlanetGrid::GridBound tileBound;
+ theGrid->bounds(theTerrainTile->tileId(), tileBound);
+ osg::Vec2d metersPerPixel;
+ theGrid->getUnitsPerPixel(metersPerPixel, theTerrainTile->tileId(), numCols, numRows, OSSIM_METERS);
+
+ ossim_uint32 rowIdx=0,colIdx=0;
+
+ // This is the grid model point. For this technique it should be lon, lat and height format
+ // stored in x, y, z
+ //
+ ossimPlanetGrid::ModelPoint centerModel;
+ theGrid->centerModel(theTerrainTile->tileId(), centerModel);
+ osg::Matrixd localToWorld;
+ // for our lsr let's always use te ellipsoid height of 0. This will make things easier later
+ //
+ theModel->lsrMatrix(osg::Vec3d(centerModel.y(),
+ centerModel.x(),
+ 0.0),//centerModel.z()),
+ localToWorld);
+ osg::Matrixd inverseLocalToWorld;
+ inverseLocalToWorld.invert(localToWorld);
+ theModel->forward(osg::Vec3d(centerModel.y(), centerModel.x(), centerModel.z()),
+ buffer.theCenterPatch);
+ osg::Vec3d centerNormal, rightAxis, upAxis;
+ centerNormal = osg::Vec3d(localToWorld(2, 0),
+ localToWorld(2, 1),
+ localToWorld(2, 2));
+ rightAxis = osg::Vec3d(localToWorld(0, 0),
+ localToWorld(0, 1),
+ localToWorld(0, 2));
+ upAxis = osg::Vec3d(localToWorld(1, 0),
+ localToWorld(1, 1),
+ localToWorld(1, 2));
+ osg::Vec2d normalDistance(0.0,0.0);
+ osg::Vec2d rightDistance(0.0,0.0);
+ osg::Vec2d upDistance(0.0,0.0);
+ double upDelta = 0.0;
+ double rightDelta = 0.0;
+ double normDelta = 0.0;
+ osg::Vec3d deltaP(0.0,0.0,0.0);
+ osg::ref_ptr<osg::Vec2Array> tcoords = new osg::Vec2Array;
+ tcoords->reserve(numVertices);
+ geometry->setTexCoordArray( 0, tcoords.get());
+
+ osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
+ vertices->reserve(numVertices);
+ geometry->setVertexArray(vertices.get());
+
+ // allocate and assign normals
+ osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
+ normals->reserve(numVertices);
+ osg::ref_ptr<osg::Vec3Array> skirtNormals = new osg::Vec3Array;
+ skirtNormals->reserve(numVertices);
+ geometry->setNormalArray(normals.get());
+ geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+
+ // allocate and assign color
+ osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
+ (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
+
+ geometry->setColorArray(colors.get());
+ geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+
+ ossimPlanetGrid::ModelPoint modelPoint;
+ osg::Vec3d norm1;
+ osg::Vec3d xyz;
+ osg::Vec3d localXYZ;
+ ossimPlanetGrid::LocalNdcPoint localPoint;
+ const ossimPlanetTerrainTileId tileId = theTerrainTile->tileId();
+ typedef std::vector<int> Indices;
+ Indices indices(numVertices, -1);
+ osg::Vec3d centerBox = buffer.theCenterPatch;
+ ossim_uint32 elevIdx = 0;
+ // double minHeight = 1.0/FLT_EPSILON;
+ // double maxHeight = -minHeight;
+ double elevationExaggeration = theTerrainTile->terrain()->elevationExaggeration();
+ if(elevationImage.valid()&&(elevationImage->hasMinMax()))
+ {
+ // minHeight = (elevationImage->minValue()[0]*elevationExaggeration)*theModel->getInvNormalizationScale();
+ // maxHeight = (elevationImage->maxValue()[0]*elevationExaggeration)*theModel->getInvNormalizationScale();
+ }
+ else
+ {
+ // minHeight = 0.0;
+ // maxHeight = 0.0;
+ }
+#if 0
+ std::cout << "minHeight = " << minHeight << std::endl;
+ std::cout << "maxHeight = " << maxHeight << std::endl;
+ std::cout << "w = " << numCols << std::endl;
+ std::cout << "h = " << numRows << std::endl;
+ std::cout << "padding = " << padding << std::endl;
+#endif
+ ossim_uint32 baseIdx = 0;
+ unsigned int iv = 0;
+ double txInc = 1.0/(numCols-1.0);
+ double tyInc = 1.0/(numRows-1.0);
+ double ty = 0.0;
+ osgUtil::Simplifier::IndexList pointsToProtect;
+ for(rowIdx = 0; rowIdx < numRows;++rowIdx)
+ {
+ double tx = 0.0;
+ localPoint.setY(ty);//(double)(rowIdx)/(double)(numRows-1));
+ for(colIdx = 0; colIdx < numCols;++colIdx)
+ {
+ // if(elevationData)
+ if(elevationImage.valid())
+ {
+ double h = elevationImage->elevationValue(colIdx+padding, rowIdx+padding);
+ if((h == OSSIMPLANET_NULL_HEIGHT)||
+ (ossim::isnan(h)))
+ {
+ h = 0;
+ }
+ else
+ {
+ h*=elevationExaggeration;
+ }
+ // if(h < minHeight) minHeight = h;
+ // if(h > maxHeight) maxHeight = h;
+ localPoint.setZ(h);
+ }
+ //rowIdx*numCols + colIdx;
+ indices[iv] = vertices->size();
+ if((colIdx == 0)||(rowIdx==0)||(rowIdx==(numRows-1)) || (colIdx == (numCols-1)))
+ {
+ pointsToProtect.push_back(indices[iv]);
+ }
+ localPoint.setX(tx);//(double)(colIdx)/(double)(numCols-1));
+ tcoords->push_back(osg::Vec2d(tx, ty));//osg::Vec2d(localPoint.x(), localPoint.y()));
+ theGrid->localNdcToModel(tileId, localPoint, modelPoint);
+ osg::Vec3d llh(modelPoint.y(), modelPoint.x(), modelPoint.z());
+ theModel->forward(llh, xyz);
+#if 1
+ deltaP = (xyz-centerBox);
+ upDelta = deltaP*upAxis;
+ rightDelta = deltaP*rightAxis;
+ normDelta = deltaP*centerNormal;
+
+ if(normDelta < normalDistance[1]) normalDistance[1] = normDelta;
+ if(normDelta > normalDistance[0]) normalDistance[0] = normDelta;
+ if(upDelta < upDistance[1]) upDistance[1] = upDelta;
+ if(upDelta > upDistance[0]) upDistance[0] = upDelta;
+ if(rightDelta < rightDistance[1]) rightDistance[1] = rightDelta;
+ if(rightDelta > rightDistance[0]) rightDistance[0] = rightDelta;
+#endif
+ localXYZ = xyz*inverseLocalToWorld;
+ (*vertices).push_back(localXYZ);
+ theModel->normal(xyz,
+ norm1);
+ osg::Vec3d tempNorm(norm1);
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ // first push gravitational normal for skirts so they point straight down
+ (*skirtNormals).push_back(norm1);
+
+ // now calculate a perturbed normal using the elevation grids
+ //
+ if(elevationImage.valid())
+ {
+ osg::Vec2d normDeltas;
+ osg::Matrixd tempLocalToWorld;
+ theModel->lsrMatrix(osg::Vec3d(llh[0],
+ llh[1],
+ llh[2]),
+ tempLocalToWorld);
+ osg::Vec3d xAxis(tempLocalToWorld(0,0), tempLocalToWorld(0,1), tempLocalToWorld(0,2));
+ osg::Vec3d yAxis(tempLocalToWorld(1,0), tempLocalToWorld(1,1), tempLocalToWorld(1,2));
+ osg::Vec3d zAxis(tempLocalToWorld(2,0), tempLocalToWorld(2,1), tempLocalToWorld(2,2));
+ osg::Matrixd composite = tempLocalToWorld*inverseLocalToWorld;
+ normDeltas = elevationImage->deltas(colIdx+padding, rowIdx+padding);
+ normDeltas = normDeltas*elevationExaggeration;
+ normDeltas[0]/=(metersPerPixel[0]);
+ normDeltas[1]/=(metersPerPixel[1]);
+ normDeltas[0] *=theModel->getInvNormalizationScale();
+ normDeltas[1] *=theModel->getInvNormalizationScale();
+ tempNorm = osg::Vec3d(-normDeltas[0], -normDeltas[1], theModel->getInvNormalizationScale());
+ tempNorm.normalize();
+ norm1 = zAxis*tempNorm[2] + xAxis*tempNorm[0] + yAxis*tempNorm[1];
+ norm1 = osg::Matrixd::transform3x3(localToWorld, norm1);
+ norm1.normalize();
+ }
+ // push perturbed normal.
+ (*normals).push_back(norm1);
+#if 0
+ deltaP = (centerBox-centerBox);
+ upDelta = deltaP*upAxis;
+ rightDelta = deltaP*rightAxis;
+ normDelta = deltaP*centerNormal;
+
+ if(normDelta < normalDistance[1]) normalDistance[1] = normDelta;
+ if(normDelta > normalDistance[0]) normalDistance[0] = normDelta;
+ if(upDelta < upDistance[1]) upDistance[1] = upDelta;
+ if(upDelta > upDistance[0]) upDistance[0] = upDelta;
+ if(rightDelta < rightDistance[1]) rightDistance[1] = rightDelta;
+ if(rightDelta > rightDistance[0]) rightDistance[0] = rightDelta;
+#endif
+ ++elevIdx;
+ ++iv;
+ tx+=txInc;
+ }
+ ty += tyInc;
+ }
+#if 0
+ osg::Vec3d bbp0 = (*vertices)[0];
+ osg::Vec3d bbp1 = (*vertices)[numCols-1];
+ osg::Vec3d bbp2 = (*vertices)[(numRows-1)*numCols + numCols-1];
+ osg::Vec3d bbp3 = (*vertices)[(numRows-1)*numCols];
+ osg::Vec3d bboxCenter;
+ osg::Vec3d bboxNormal;
+ osg::Vec2d bboxNormalDistance;
+ bboxNormalDistance[0] = 0.0;
+ bboxNormalDistance[1] = 0.0;
+
+ averageNormal(bboxCenter, bboxNormal,
+ bbp0,
+ bbp1,
+ bbp2,
+ bbp3);
+ ossim_uint32 idx = 0;
+ osg::Vec3d tempPoint;
+ double projValue = 0.0;
+ for(idx = 0; idx < (*vertices).size();++idx)
+ {
+ tempPoint = osg::Vec3d((*vertices)[idx])-bboxCenter;
+ projValue = tempPoint*bboxNormal;
+ if(projValue > bboxNormalDistance[0]) bboxNormalDistance[0] = projValue;
+ if(projValue < bboxNormalDistance[1]) bboxNormalDistance[1] = projValue;
+ }
+#endif
+ osg::ref_ptr<ossimPlanetBoundingBox> box = new ossimPlanetBoundingBox();
+ // box->extrude(bbp0,
+ // bbp1,
+ // bbp2,
+ // bbp3,
+ // bboxNormal,
+ // bboxNormalDistance);
+ box->extrude(centerBox,//buffer.theCenterPatch,
+ upAxis,
+ rightAxis,
+ centerNormal,
+ upDistance,
+ rightDistance,
+ normalDistance);
+ // double defaultDeltaHeight = fabs(normalDistance[0] - normalDistance[1]);
+ box->transform(inverseLocalToWorld);
+
+ buffer.theTransform->setMatrix(localToWorld);
+
+ // now lit's do the skirt if enabled
+ // for now it's always enabled but will add a flag later to turn it off and
+ // on
+ //
+ osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*skirtNormals));
+ // let do bottom part
+ //
+
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES));
+ osg::Geometry::PrimitiveSetList primSetList;
+ ossim_uint32 i = 0;
+ ossim_uint32 j = 0;
+
+#if 0
+ for(j = 0; j < numRows-1;++j)
+ {
+ for(i = 0; i < numCols-1; ++i)
+ {
+ int i00;
+ int i01;
+ i00 = j*numCols + i;
+ i01 = i00+numCols;
+
+ int i10 = i00+1;
+ int i11 = i01+1;
+
+ // remap indices to final vertex positions
+ i00 = indices[i00];
+ i01 = indices[i01];
+ i10 = indices[i10];
+ i11 = indices[i11];
+
+ if(i!=j)
+ {
+ drawElements.push_back(i10);
+ drawElements.push_back(i01);
+ drawElements.push_back(i00);
+
+ drawElements.push_back(i10);
+ drawElements.push_back(i11);
+ drawElements.push_back(i01);
+ }
+ else
+ {
+ drawElements.push_back(i01);
+ drawElements.push_back(i00);
+ drawElements.push_back(i11);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i10);
+ drawElements.push_back(i11);
+ }
+
+ }
+ }
+#else
+ for(i = 1; i < numRows;i+=2)
+ {
+ for(j = 1; j < numCols;j+=2)
+ {
+ ossim_uint32 i00 = (i)*numCols + j;
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols+1));
+ drawElements.push_back(i00 - (numCols));
+
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols));
+ drawElements.push_back(i00 - (numCols-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - (numCols-1));
+ drawElements.push_back(i00 + 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + 1);
+ drawElements.push_back(i00 + (numCols+1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols+1));
+ drawElements.push_back(i00 + (numCols));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols));
+ drawElements.push_back(i00 + (numCols-1));
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 + (numCols-1));
+ drawElements.push_back(i00 - 1);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i00 - 1);
+ drawElements.push_back(i00 - (numCols+1));
+ }
+ }
+#endif
+ primSetList.push_back(&drawElements);
+ geometry->setPrimitiveSetList(primSetList);
+ //osgUtil::Simplifier simplifier(.8);
+ //simplifier.simplify(*geometry, pointsToProtect);
+ geometry->dirtyBound();
+ geometry->getBound();
+ thePatchBound = buffer.theTransform->getBound();
+ ossimPlanetGrid::ModelPoint centerModelPoint;
+ theGrid->centerModel(theTerrainTile->tileId(), centerModelPoint);
+ theModel->latLonHeightToXyz(osg::Vec3d(centerModelPoint.y(), centerModelPoint.x(), 0.0), theCenterGrid);
+
+ buffer.theClusterCullingCallback->computeFrom(geometry);
+ //smoothGeometry();
+ buffer.theCullNode = new CullNode(theTerrainTile->tileId(),
+ box.get(),
+ buffer.theClusterCullingCallback->getControlPoint(),
+ buffer.theClusterCullingCallback->getNormal(),
+ (double)buffer.theClusterCullingCallback->getDeviation(),
+ (double)buffer.theClusterCullingCallback->getRadius());
+ buffer.theCullNode->setMatrix(buffer.theTransform->getMatrix());
+ buffer.theCullNode->dirtyBound();
+ ossim_uint32 c = 0;
+ ossim_uint32 r = 0;
+ ossim_float32 bottomSkirtHeight = buffer.theTransform->getBound().radius()*skirtScale;
+ ossim_float32 rightSkirtHeight = bottomSkirtHeight;
+ ossim_float32 topSkirtHeight = bottomSkirtHeight;
+ ossim_float32 leftSkirtHeight = bottomSkirtHeight;
+
+#if 0
+ if(elevationData)
+ {
+ // bottom variance
+ ossim_int32 i = indices[numCols>>1]; // index of original vertex of grid
+ osg::Vec3d centerEdgeNormal = (*normals)[i];
+ osg::Vec3d centerControlPoint = (*vertices)[i];
+ ossim_float32 heightValue = 0.0;
+ minHeight = 1.0/FLT_EPSILON;
+ maxHeight = -minHeight;
+ ossim_float32 heightVariance = 0.0;
+ for(c = 0; c < numCols; ++c)
+ {
+ i = indices[c]; // index of original vertex of grid
+ heightValue = ((*vertices)[i]-centerControlPoint)*centerEdgeNormal;
+ if(maxHeight < heightValue) maxHeight = heightValue;
+ if(minHeight > heightValue) minHeight = heightValue;
+ }
+ heightVariance = (maxHeight-minHeight);///theModel->getNormalizationScale();
+ bottomSkirtHeight = heightVariance;//ossim::max(bottomSkirtHeight, heightVariance);
+
+ // right variance
+ //
+ minHeight = 1.0/FLT_EPSILON;
+ maxHeight = -minHeight;
+ baseIdx = numCols-1;
+ i = indices[baseIdx + numCols*(numRows>>1)];
+ centerEdgeNormal = (*normals)[i];
+ centerControlPoint = (*vertices)[i];
+ for(r = 0; r < numRows; ++r)
+ {
+ i = indices[baseIdx]; // index of original vertex of grid
+ heightValue = ((*vertices)[i]-centerControlPoint)*centerEdgeNormal;
+ if(maxHeight < heightValue) maxHeight = heightValue;
+ if(minHeight > heightValue) minHeight = heightValue;
+ baseIdx+=numCols;
+ }
+ heightVariance = (maxHeight-minHeight);///theModel->getNormalizationScale();
+ rightSkirtHeight = heightVariance;//ossim::max(rightSkirtHeight, heightVariance);
+
+ // top variance
+ //
+ minHeight = 1.0/FLT_EPSILON;
+ maxHeight = -minHeight;
+ baseIdx = numCols*(numRows-1);
+ i = indices[baseIdx + (numCols>>1)];
+ centerEdgeNormal = (*normals)[i];
+ centerControlPoint = (*vertices)[i];
+ for(c = 0; c < numCols; ++c)
+ {
+ i = indices[baseIdx]; // index of original vertex of grid
+ heightValue = ((*vertices)[i]-centerControlPoint)*centerEdgeNormal;
+ if(maxHeight < heightValue) maxHeight = heightValue;
+ if(minHeight > heightValue) minHeight = heightValue;
+ ++baseIdx;
+ }
+ heightVariance = (maxHeight-minHeight);
+ topSkirtHeight = heightVariance;//ossim::max(topSkirtHeight, heightVariance);
+
+ // left variance
+ //
+ minHeight = 1.0/FLT_EPSILON;
+ maxHeight = -minHeight;
+ baseIdx = 0;
+ i = indices[baseIdx + numCols*(numRows>>1)];
+ centerEdgeNormal = (*normals)[i];
+ centerControlPoint = (*vertices)[i];
+ for(r = 0; r < numRows; ++r)
+ {
+ i = indices[baseIdx]; // index of original vertex of grid
+ heightValue = ((*vertices)[i]-centerControlPoint)*centerEdgeNormal;
+ if(maxHeight < heightValue) maxHeight = heightValue;
+ if(minHeight > heightValue) minHeight = heightValue;
+ baseIdx += numCols;
+ }
+ heightVariance = (maxHeight-minHeight);
+ leftSkirtHeight = heightVariance;//ossim::max(leftSkirtHeight, heightVariance);
+ }
+#endif
+ ossim_uint32 skirtFlags = computeSkirtFlags(theTerrainTile->tileId());
+ if(skirtFlags&BOTTOM_SKIRT)
+ {
+ // let's do the bottom skirt first
+ //
+ r = 0;
+ for(c = 0; c < numCols; ++c)
+ {
+ ossim_uint32 idx = c;//numCols+c;
+ ossim_int32 orig_i = indices[idx]; // index of original vertex of grid
+ unsigned int new_i = vertices->size(); // index of new index of added skirt point
+ osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*bottomSkirtHeight;
+ (*vertices).push_back(new_v);
+ (*normals).push_back((*normals)[orig_i]);
+
+ tcoords->push_back((*tcoords)[orig_i]);
+ if(((c % 2) == 0)&&
+ (c>0))
+ {
+ drawElements.push_back(indices[idx-2]);
+ drawElements.push_back(new_i-2);
+ drawElements.push_back(new_i-1);
+
+ drawElements.push_back(new_i-1);
+ drawElements.push_back(indices[idx-1]);
+ drawElements.push_back(indices[idx-2]);
+
+ drawElements.push_back(indices[idx-1]);
+ drawElements.push_back(new_i-1);
+ drawElements.push_back(new_i);
+
+ drawElements.push_back(new_i);
+ drawElements.push_back(indices[idx]);
+ drawElements.push_back(indices[idx-1]);
+ }
+ }
+ }
+ if(skirtFlags&RIGHT_SKIRT)
+ {
+ // now let's do right Skirt
+ //
+ baseIdx = numCols-1;
+ for(r = 0; r < numRows; ++r)
+ {
+ ossim_int32 orig_i = indices[baseIdx]; // index of original vertex of grid
+ unsigned int new_i = vertices->size(); // index of new index of added skirt point
+ osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*rightSkirtHeight;
+ (*vertices).push_back(new_v);
+ (*normals).push_back((*normals)[orig_i]);
+ tcoords->push_back((*tcoords)[orig_i]);
+ if(((r % 2) == 0)&&
+ (r>0))
+ {
+ drawElements.push_back(indices[baseIdx-(numCols<<1)]);
+ drawElements.push_back(new_i-2);
+ drawElements.push_back(new_i-1);
+
+ drawElements.push_back(new_i-1);
+ drawElements.push_back(indices[baseIdx-numCols]);
+ drawElements.push_back(indices[baseIdx-(numCols<<1)]);
+
+ drawElements.push_back(indices[baseIdx-numCols]);
+ drawElements.push_back(new_i-1);
+ drawElements.push_back(new_i);
+
+ drawElements.push_back(new_i);
+ drawElements.push_back(indices[baseIdx]);
+ drawElements.push_back(indices[baseIdx-numCols]);
+ }
+ baseIdx+=numCols;
+ }
+ }
+
+ if(skirtFlags&TOP_SKIRT)
+ {
+ // top skirt
+ baseIdx = numCols*(numRows-1);
+ for(c = 0; c < numCols; ++c)
+ {
+ ossim_int32 orig_i = indices[baseIdx]; // index of original vertex of grid
+ unsigned int new_i = vertices->size(); // index of new index of added skirt point
+ osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*topSkirtHeight;
+ (*vertices).push_back(new_v);
+ (*normals).push_back((*normals)[orig_i]);
+ tcoords->push_back((*tcoords)[orig_i]);
+ if(((c % 2) == 0)&&
+ (c>0))
+ {
+ drawElements.push_back(indices[baseIdx-2]);
+ drawElements.push_back(new_i-1);
+ drawElements.push_back(new_i-2);
+
+ drawElements.push_back(indices[baseIdx-2]);
+ drawElements.push_back(indices[baseIdx-1]);
+ drawElements.push_back(new_i-1);
+
+ drawElements.push_back(indices[baseIdx-1]);
+ drawElements.push_back(new_i);
+ drawElements.push_back(new_i-1);
+
+ drawElements.push_back(indices[baseIdx]-1);
+ drawElements.push_back(indices[baseIdx]);
+ drawElements.push_back(new_i);
+ }
+
+ ++baseIdx;
+ }
+ }
+
+ if(skirtFlags&LEFT_SKIRT)
+ {
+ // now do left skirt
+ //
+ baseIdx = 0;
+ for(r = 0; r < numRows; ++r)
+ {
+ ossim_int32 orig_i = indices[baseIdx]; // index of original vertex of grid
+ unsigned int new_i = vertices->size(); // index of new index of added skirt point
+ osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*leftSkirtHeight;
+ (*vertices).push_back(new_v);
+ (*normals).push_back((*normals)[orig_i]);
+ tcoords->push_back((*tcoords)[orig_i]);
+ if(((r % 2) == 0)&&
+ (r>0))
+ {
+ drawElements.push_back(indices[baseIdx-(numCols<<1)]);
+ drawElements.push_back(new_i-1);
+ drawElements.push_back(new_i-2);
+
+ drawElements.push_back(indices[baseIdx-(numCols<<1)]);
+ drawElements.push_back(indices[baseIdx-numCols]);
+ drawElements.push_back(new_i-1);
+
+ drawElements.push_back(indices[baseIdx-numCols]);
+ drawElements.push_back(new_i);
+ drawElements.push_back(new_i-1);
+
+ drawElements.push_back(indices[baseIdx-numCols]);
+ drawElements.push_back(indices[baseIdx]);
+ drawElements.push_back(new_i);
+ }
+ baseIdx += numCols;
+ }
+ }
+#if 0
+ osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES));
+ osg::Geometry::PrimitiveSetList primSetList;
+ ossim_uint32 i = 0;
+ ossim_uint32 j = 0;
+ ossim_uint32 i00 = 0;
+ ossim_uint32 i01 = 0;
+ ossim_uint32 i10 = 0;
+ ossim_uint32 i11 = 0;
+ bool swapOrientation = theTerrainTile->tileId().face() > 3;
+ for(j = 0; j < numRows-1;++j)
+ {
+ for(i = 0; i < numCols-1;++i)
+ {
+ // if (swapOrientation)
+ // {
+ // i01 = j*numCols + i;
+ // i00 = i01+numCols;
+ // }
+ // else
+ // {
+ i00 = j*numCols + i;
+ i01 = i00+numCols;
+ // }
+ i10 = i00+1;
+ i11 = i01+1;
+ // i00 = indices[i00];
+ // i01 = indices[i01];
+ // i10 = indices[i10];
+ // i11 = indices[i11];
+ if(!swapOrientation)
+ {
+ drawElements.push_back(i01);
+ drawElements.push_back(i00);
+ drawElements.push_back(i11);
+
+ drawElements.push_back(i00);
+ drawElements.push_back(i10);
+ drawElements.push_back(i11);
+ }
+ else
+ {
+ drawElements.push_back(i01);
+ drawElements.push_back(i00);
+ drawElements.push_back(i10);
+
+ drawElements.push_back(i01);
+ drawElements.push_back(i10);
+ drawElements.push_back(i11);
+
+ }
+ }
+ }
+ primSetList.push_back(&drawElements);
+ geometry->setPrimitiveSetList(primSetList);
+#endif
+
+ //smoothGeometry();
+ osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace;
+ geometry->getOrCreateStateSet()->setAttributeAndModes(cullFace.get(),
+ osg::StateAttribute::ON);
+ // if(theCullSettings&osg::CullSettings::CLUSTER_CULLING)
+ // {
+ // geometry->setCullCallback(buffer.theClusterCullingCallback.get());
+ // }
+ geometry->setUseVertexBufferObjects(true);
+ geometry->setUseDisplayList(false);
+// geometry->setFastPathHint(true);
+
+
+ if (osgDB::Registry::instance()->getBuildKdTreesHint()==osgDB::ReaderWriter::Options::BUILD_KDTREES &&
+ osgDB::Registry::instance()->getKdTreeBuilder())
+ {
+
+
+ //osg::Timer_t before = osg::Timer::instance()->tick();
+ //osg::notify(osg::NOTICE)<<"osgTerrain::GeometryTechnique::build kd tree"<<std::endl;
+ osg::ref_ptr<osg::KdTreeBuilder> builder = osgDB::Registry::instance()->getKdTreeBuilder()->clone();
+ buffer.theGeode->accept(*builder);
+ //std::cout << "BUILT!!" << std::endl;
+ //osg::Timer_t after = osg::Timer::instance()->tick();
+ //osg::notify(osg::NOTICE)<<"KdTree build time "<<osg::Timer::instance()->delta_m(before, after)<<std::endl;
+ }
+
+ buffer.theGeode->dirtyBound();
+ buffer.theTransform->dirtyBound();
+ buffer.theGeometry->dirtyBound();
+ buffer.theTransform->getBound();
+#if 0
+ ossimPlanetTerrainTile* parent = optionalParent?optionalParent:theTerrainTile->parentTile();
+ if(theTerrainTile)
+ {
+ theTerrainTile->dirtyBound();
+ theTerrainTile->getBound();
+ }
+ // now copy cull node settings to the parent so it's always cached
+ //
+ if(parent)
+ {
+ ((ossimPlanetTerrainGeometryTechnique*)(parent->terrainTechnique()))->setChildCullParameters(theTerrainTile,
+ buffer.theCullNode);
+ }
+#endif
+}
+
+ossimPlanetTexture2D* ossimPlanetTerrainGeometryTechnique::findNearestActiveParentTexture(ossim_uint32 imageLayerIdx,
+ ossimPlanetTerrainTile* optionalParent)
+{
+ if(!theTerrainTile) return 0;
+ ossimPlanetTerrainTile* parent = optionalParent?optionalParent:theTerrainTile->parentTile();
+ ossimPlanetTerrainGeometryTechnique* currentTechnique =
+ dynamic_cast<ossimPlanetTerrainGeometryTechnique*>(parent?parent->terrainTechnique():0);
+ ossimPlanetTexture2D* result = 0;
+ while(!result&¤tTechnique)
+ {
+ BufferData& buffer = currentTechnique->readOnlyBuffer();
+ if(buffer.theTransform.valid())
+ {
+ osg::StateSet* stateset = buffer.theGeode->getStateSet();
+ if(stateset)
+ {
+ result = dynamic_cast<ossimPlanetTexture2D*>(stateset->getTextureAttribute(imageLayerIdx,
+ osg::StateAttribute::TEXTURE));
+
+ // if(!result->getImage())
+ // {
+ // result = 0;
+ // }
+ }
+ parent = parent->parentTile();
+ if(parent)
+ {
+ currentTechnique = dynamic_cast<ossimPlanetTerrainGeometryTechnique*>(parent->terrainTechnique());
+ }
+ else
+ {
+ currentTechnique = 0;
+ }
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetTerrainGeometryTechnique::applyColorLayers(ossimPlanetTerrainTile* optionalParent)
+{
+ if(!theTerrainTile) return;
+ BufferData& buffer = writeBuffer();
+ if(!buffer.theTransform.valid()) return;
+ typedef std::map<ossimPlanetTerrainLayer*, osg::ref_ptr<osg::Texture> > LayerToTextureMap;
+ LayerToTextureMap layerToTextureMap;
+
+ ossim_uint32 imageLayerIdx = 0;
+ for(imageLayerIdx=0; imageLayerIdx<theTerrainTile->numberOfImageLayers(); ++imageLayerIdx)
+ {
+ ossimPlanetTerrainImageLayer* imageLayer = theTerrainTile->imageLayer(imageLayerIdx);
+ if (!imageLayer) continue;
+ osg::ref_ptr<ossimPlanetImage> image = imageLayer->image();
+
+ osg::ref_ptr<ossimPlanetTexture2D> borrowedTexture = 0;
+ if (!image)
+ {
+ borrowedTexture = findNearestActiveParentTexture(imageLayerIdx, optionalParent);
+ //std::cout << theTerrainTile->tileId().level() << " TRYING TO BORROW\n";
+ //std::cout << borrowedTexture.get() << std::endl;
+ // borrow gl texture from parent
+ //
+ if(!borrowedTexture) continue;
+ }
+ osg::ref_ptr<osg::StateSet> stateset = buffer.theGeode->getOrCreateStateSet();
+ osg::ref_ptr<ossimPlanetTexture2D> texture2D = borrowedTexture.get();//borrowedTexture.valid()?borrowedTexture.get():
+ //dynamic_cast<ossimPlanetTexture2D*>(layerToTextureMap[imageLayer].get());
+ imageLayer->setDirtyFlag(false);
+
+ if(!texture2D)
+ {
+ texture2D = dynamic_cast<ossimPlanetTexture2D*>(stateset->getTextureAttribute(imageLayerIdx,
+ osg::StateAttribute::TEXTURE));
+ if(!texture2D)
+ {
+ texture2D = newImageLayerTexture(imageLayerIdx);
+ imageLayer->setDirtyFlag(false);
+ }
+ else if(image.valid())
+ {
+ if(texture2D->tileId().level()!=image->tileId().level())
+ {
+ texture2D = newImageLayerTexture(imageLayerIdx);
+ imageLayer->setDirtyFlag(false);
+ }
+ }
+ }
+ if(texture2D.valid()&&!borrowedTexture.valid())
+ {
+ texture2D->setFilter(osg::Texture::MIN_FILTER, imageLayer->minFilter());
+ texture2D->setFilter(osg::Texture::MAG_FILTER, imageLayer->magFilter());
+ }
+ //layerToTextureMap[imageLayer] = texture2D.get();
+ stateset->setTextureAttributeAndModes(imageLayerIdx, texture2D.get(), osg::StateAttribute::ON);
+
+ updateTextureMatrix(stateset.get(), imageLayerIdx, theTerrainTile->tileId(), texture2D->tileId());
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::applyTransparency(ossimPlanetTerrainTile* /* optionalParent */)
+{
+ BufferData& buffer = writeBuffer();
+
+ bool containsTransparency = false;
+ ossim_uint32 colorLayerIdx = 0;
+ for(colorLayerIdx=0; colorLayerIdx<theTerrainTile->numberOfImageLayers(); ++colorLayerIdx)
+ {
+ ossimPlanetTerrainImageLayer* colorLayer = theTerrainTile->imageLayer(colorLayerIdx);
+ if (!colorLayer) continue;
+
+ osg::ref_ptr<osg::Image> image = colorLayer->image();
+ if (image.valid())
+ {
+ containsTransparency = image->isImageTranslucent();
+ break;
+ }
+ }
+
+ if (containsTransparency&&buffer.theGeode.valid())
+ {
+ osg::StateSet* stateset = buffer.theGeode->getOrCreateStateSet();
+ stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
+ stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::init(ossimPlanetTerrainTile* optionalParent)
+{
+ if(!theTerrainTile) return;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildNodeCullParametersMutex);
+ if(!theChildNodeCullParameters.size())
+ {
+ theChildNodeCullParameters.resize(4);
+ }
+ }
+ if(!readOnlyBuffer().theTransform.valid()) // we need to do a full init and swap
+ {
+ buildMesh(optionalParent);
+ applyColorLayers(optionalParent);
+ applyTransparency(optionalParent);
+ swapBuffers();
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::childAdded(ossim_uint32 pos)
+{
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(theTerrainTile->getChild(pos));
+
+ if(tile)
+ {
+ // ossimPlanetTerrainGeometryTechnique* technique = dynamic_cast<ossimPlanetTerrainGeometryTechnique*>(tile->terrainTechnique());
+
+ // now lets default to a lower resolution texture for
+ // any image layers that have not been initialized
+ //
+ ossim_uint32 idx = 0;
+ ossim_uint32 numberOfImageLayers = tile->numberOfImageLayers();
+ for(idx = 0; idx < numberOfImageLayers;++idx)
+ {
+ ossimPlanetTerrainImageLayer* layer = tile->imageLayer(idx);
+ if(layer&&!layer->image())
+ {
+ ossimPlanetTexture2D* texture = findNearestActiveParentTexture(idx, tile);
+ if(texture)
+ {
+ UpdateChildTextureVisitor childTextureVisitor(texture, idx);
+ tile->accept(childTextureVisitor);
+ }
+ }
+ }
+ }
+
+
+ // theTerrainTile->dirtyBound();
+ // theTerrainTile->getBound();
+
+}
+
+void ossimPlanetTerrainGeometryTechnique::merge()
+{
+ if(!theTerrainTile) return;
+
+ ossimPlanetTerrainTile::MergeTestVisitor visitor(true);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theTerrainTile->getNumChildren();++idx)
+ {
+ theTerrainTile->getChild(idx)->accept(visitor);
+ }
+ if(visitor.canMerge())
+ {
+ theTerrainTile->removeChildren(0, theTerrainTile->getNumChildren());
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::removeCulledChildren()
+{
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = theChildNodeCullParameters.size();
+ for(idx = 0; idx < bound; ++idx)
+ {
+ if(theChildNodeCullParameters[idx].valid())
+ {
+
+ ossimPlanetTerrainTile* tile = theTerrainTile->child(theChildNodeCullParameters[idx]->tileId());
+ if(tile&&theChildNodeCullParameters[idx]->isCulled())
+ {
+ theTerrainTile->removeChild(tile);
+ }
+ }
+ }
+}
+
+bool ossimPlanetTerrainGeometryTechnique::hasCulledChildren()const
+{
+ if(theTerrainTile->getNumChildren() < 1) return false;
+ ossim_uint32 idx = 0;
+ ossim_uint32 bounds = theTerrainTile->getNumChildren();
+ for(idx = 0; idx < bounds; ++idx)
+ {
+ const ossimPlanetTerrainTile* tile = dynamic_cast<const ossimPlanetTerrainTile*>(theTerrainTile->getChild(idx));
+ if(tile)
+ {
+ if(tile->culledFlag()) return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool ossimPlanetTerrainGeometryTechnique::isChildCulled(ossim_uint32 childIdx)const
+{
+ if(theChildNodeCullParameters[childIdx].valid())
+ {
+ return theChildNodeCullParameters[childIdx]->isCulled();
+ }
+
+ return false;
+}
+
+double ossimPlanetTerrainGeometryTechnique::texturePriority()const
+{
+ if(!theTerrainTile) return 0.0;
+
+ // const BufferData& buffer = readOnlyBuffer();
+ double result = 0.0;
+ // double distance = 0.0;
+ // result = (thePriorityPoint - thePatchBound.center()).length();
+
+ result =(thePriorityPoint-theCenterGrid).length();
+
+ result = -result;
+
+ return result;
+}
+
+double ossimPlanetTerrainGeometryTechnique::elevationPriority()const
+{
+ return texturePriority();
+}
+
+double ossimPlanetTerrainGeometryTechnique::mergePriority()const
+{
+ return texturePriority();
+}
+
+double ossimPlanetTerrainGeometryTechnique::splitPriority()const
+{
+ return texturePriority();
+}
+
+void ossimPlanetTerrainGeometryTechnique::smoothGeometry()
+{
+ BufferData& buffer = writeBuffer();
+
+ if (buffer.theGeometry.valid())
+ {
+ osgUtil::SmoothingVisitor smoother;
+ smoother.smooth(*buffer.theGeometry);
+ }
+}
+
+osg::BoundingSphere ossimPlanetTerrainGeometryTechnique::computeBound() const
+{
+ const BufferData& buffer = readOnlyBuffer();
+ if(buffer.theTransform.valid())
+ {
+ return readOnlyBuffer().theTransform->getBound();
+ }
+ return osg::BoundingSphere(osg::Vec3d(0.0,0.0,0.0), -1);
+
+}
+
+bool ossimPlanetTerrainGeometryTechnique::isCulled(BufferData& buffer, osgUtil::CullVisitor* cv)const
+{
+ if(cv->getCullingMode() == osg::CullSettings::NO_CULLING) return false;
+
+ buffer.theCullNode->accept(*cv);
+ bool result = buffer.theCullNode->isCulled();
+ if(!result)
+ {
+ result = cv->isCulled(thePatchBound);
+ }
+ return result;
+}
+
+void ossimPlanetTerrainGeometryTechnique::setChildCullParameters(ossimPlanetTerrainTile* tile,
+ osg::ref_ptr<CullNode> cullNode)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildNodeCullParametersMutex);
+
+ if(theChildNodeCullParameters.size() != 4)
+ {
+ theChildNodeCullParameters.resize(4);
+ }
+ ossim_uint32 idx = childIndex(tile->tileId());
+ // this is a quad tree so look at eve odd values.
+ //
+ if(idx < theChildNodeCullParameters.size())
+ {
+ theChildNodeCullParameters[idx] = cullNode.get();
+ }
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::markOnlyNeededChildImageLayersDirty()
+{
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = theTerrainTile->getNumChildren();
+
+ for(idx = 0; idx < bound; ++idx)
+ {
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(theTerrainTile->getChild(idx));
+ if(tile)
+ {
+ ossim_uint32 idxLayer = 0;
+ ossim_uint32 imageLayerBound = tile->numberOfImageLayers();
+ for(idxLayer = 0; idxLayer < imageLayerBound; ++idxLayer)
+ {
+ //if(theTerrainTile->imageLayer(idxLayer)->isDirty())
+ {
+ osg::ref_ptr<ossimPlanetImage> image = tile->imageLayer(idxLayer)->image();
+
+ // if he is borrowing from a parent Texture make sure he get's reset
+ //
+ if(!image || (image->tileId().level()!=tile->tileId().level()))
+ {
+ tile->imageLayer(idxLayer)->setDirtyFlag(true);
+ }
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::updateElevationMesh()
+{
+ BufferData& buffer = writeBuffer();
+ osg::ref_ptr<osg::StateSet> stateset;
+ if(buffer.theGeode.valid())
+ {
+ stateset = buffer.theGeode->getStateSet();
+ }
+ buildMesh();
+ if(stateset.valid())
+ {
+ if(stateset.valid()&&buffer.theGeode.valid())
+ {
+ buffer.theGeode->setStateSet(stateset.get());
+ }
+ }
+}
+
+ossimPlanetTexture2D* ossimPlanetTerrainGeometryTechnique::newImageLayerTexture(ossim_uint32 imageLayerIdx)
+{
+ ossimPlanetTexture2D* texture2D = new ossimPlanetTexture2D;
+ osg::ref_ptr<ossimPlanetImage> image;
+ ossimPlanetTerrainImageLayer* layer =0;
+ if(theTerrainTile)
+ {
+ layer = theTerrainTile->imageLayer(imageLayerIdx);
+ if(layer)
+ {
+ image = layer->image();
+ }
+ }
+ if(image.valid())
+ {
+ texture2D->setImage(image.get());
+ }
+ // texture2D->setMaxAnisotropy(16.0f);
+ texture2D->setResizeNonPowerOfTwoHint(false);
+ if(layer)
+ {
+ texture2D->setFilter(osg::Texture2D::MIN_FILTER,layer->minFilter());
+ texture2D->setFilter(osg::Texture2D::MAG_FILTER,layer->magFilter());
+ }
+ texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
+ texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
+ texture2D->setDataVariance(osg::Object::DYNAMIC);
+ texture2D->setUnRefImageDataAfterApply(false);
+
+ return texture2D;
+}
+
+void ossimPlanetTerrainGeometryTechnique::compileGlObjects(osg::State* state)
+{
+ BufferData& buffer = readOnlyBuffer();
+ if(buffer.theGeode.valid())
+ {
+ ossimPlanetTerrainTechnique::CompileObjects visitor;
+ visitor.setState(state);
+ buffer.theTransform->accept(visitor);
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::setImageLayerTexture(ossimPlanetTexture2D* texture,
+ ossim_uint32 imageLayerIdx)
+{
+ BufferData& buffer = readOnlyBuffer();
+ if(texture&&buffer.theGeode.valid())
+ {
+ osg::StateSet* stateset = buffer.theGeode->getOrCreateStateSet();
+ if(texture->tileId().level() == theTerrainTile->tileId().level())
+ {
+ ossimPlanetImage* image = dynamic_cast<ossimPlanetImage*>(texture->getImage());
+ if(image)
+ {
+ ossimPlanetTerrainImageLayer* imageLayer = theTerrainTile->imageLayer(imageLayerIdx);
+ if(imageLayer)
+ {
+ imageLayer->setImage(image);
+ imageLayer->setDirtyFlag(false);
+ imageLayer->setRefreshFlag(false);
+ }
+ }
+ }
+ if(stateset)
+ {
+ stateset->setTextureAttributeAndModes(imageLayerIdx, texture, osg::StateAttribute::ON);
+ updateTextureMatrix(stateset, imageLayerIdx, theTerrainTile->tileId(), texture->tileId());
+ }
+ UpdateChildTextureVisitor visitor(texture, imageLayerIdx);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theTerrainTile->getNumChildren();++idx)
+ {
+ theTerrainTile->getChild(idx)->accept(visitor);
+ }
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::updateTextureMatrix(osg::StateSet* stateset,
+ ossim_uint32 imageLayerIdx,
+ const ossimPlanetTerrainTileId& startId,
+ const ossimPlanetTerrainTileId& endId)
+{
+ if(startId.level() != endId.level())
+ {
+ osg::Matrixd texMat;
+ solveTextureMatrixMappingToParent(startId, endId, texMat);
+ osg::TexMat* texMatAttribute = new osg::TexMat(texMat);
+ stateset->setTextureAttributeAndModes(imageLayerIdx, texMatAttribute, osg::StateAttribute::ON);
+ }
+ else
+ {
+ stateset->removeTextureAttribute(imageLayerIdx, osg::StateAttribute::TEXMAT);
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::setElevationMeshFrom(ossimPlanetTerrainTile* tile)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTerrainTileMutex);
+
+ if(tile&&theTerrainTile)
+ {
+ ossimPlanetTerrainGeometryTechnique* geometryTechnique = dynamic_cast<ossimPlanetTerrainGeometryTechnique*>(tile->terrainTechnique());
+ osg::ref_ptr<ossimPlanetImage> elevation = tile->elevationLayer()->image();
+ if(geometryTechnique)
+ {
+ BufferData& bufferFrom = geometryTechnique->readOnlyBuffer();
+
+ BufferData& bufferTo = writeBuffer();
+
+ if(bufferFrom.theTransform.valid())
+ {
+ if(theTerrainTile->elevationLayer()&&elevation.valid())
+ {
+ theTerrainTile->elevationLayer()->setImage(elevation.get());
+ theTerrainTile->elevationLayer()->setDirtyFlag(false);
+ theTerrainTile->elevationLayer()->setRefreshFlag(false);
+ }
+ bufferTo.theClusterCullingCallback = bufferFrom.theClusterCullingCallback;
+ osg::ref_ptr<osg::StateSet> bufferToTransformStateSet = bufferTo.theTransform->getStateSet();
+ osg::ref_ptr<osg::StateSet> bufferToGeometryStateSet = bufferTo.theGeometry->getStateSet();
+ osg::ref_ptr<osg::StateSet> bufferToGeodeStateSet = bufferTo.theGeode->getStateSet();
+
+ bufferTo.theTransform = bufferFrom.theTransform;
+ bufferTo.theGeometry = bufferFrom.theGeometry;
+ bufferTo.theGeode = bufferFrom.theGeode;
+ bufferTo.theCenterPatch = bufferFrom.theCenterPatch;
+ bufferTo.theClusterCullingCallback = bufferFrom.theClusterCullingCallback;
+
+ bufferTo.theTransform->setStateSet(bufferToTransformStateSet.get());
+ bufferTo.theGeometry->setStateSet(bufferToGeometryStateSet.get());
+ bufferTo.theGeode->setStateSet(bufferToGeodeStateSet.get());
+
+ if(theTerrainTile)
+ {
+ theTerrainTile->dirtyBound();
+ theTerrainTile->getBound();
+ }
+ // now copy cull node settings to the parent so it's always cached
+ //
+ // ossimPlanetTerrainTile* parent = theTerrainTile->parentTile();
+ swapBuffers();
+ // markOnlyNeededChildImageLayersDirty();
+ }
+ }
+ }
+}
+
+void ossimPlanetTerrainGeometryTechnique::vacantChildIds(TileIdList& ids)const
+{
+ ossimPlanetTerrainTechnique::vacantChildIds(ids);
+}
+
+ossim_uint32 ossimPlanetTerrainGeometryTechnique::computeSkirtFlags(const ossimPlanetTerrainTileId& /* childId */)const
+{
+#if 1
+ return LEFT_SKIRT|RIGHT_SKIRT|BOTTOM_SKIRT|TOP_SKIRT;
+#else
+ if(childId.level() == 0) return LEFT_SKIRT|RIGHT_SKIRT|BOTTOM_SKIRT|TOP_SKIRT;
+ ossim_uint32 result = NO_SKIRT;
+ switch(childIndex(childId))
+ {
+ case BOTTOM_LEFT: // bottom Left quadrant
+ {
+ result = BOTTOM_SKIRT|LEFT_SKIRT;
+ break;
+ }
+ case BOTTOM_RIGHT: // bottom right
+ {
+ result = BOTTOM_SKIRT|RIGHT_SKIRT;
+ break;
+ }
+ case TOP_LEFT: // top left child
+ {
+ result = TOP_SKIRT|LEFT_SKIRT;
+ break;
+ }
+ case TOP_RIGHT: // top right child
+ {
+ result = TOP_SKIRT|RIGHT_SKIRT;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return result;
+#endif
+}
+
+void ossimPlanetTerrainGeometryTechnique::releaseGLObjects(osg::State* state)
+{
+ BufferData& buffer = readOnlyBuffer();
+ if(buffer.theTransform.valid())
+ {
+ buffer.theTransform->releaseGLObjects(state);
+ buffer.theGeode->releaseGLObjects(state);
+ buffer.theGeometry->releaseGLObjects(state);
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainLayer.cpp
new file mode 100644
index 0000000..5335a3d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainLayer.cpp
@@ -0,0 +1 @@
+#include <ossimPlanet/ossimPlanetTerrainLayer.h>
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainTechnique.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainTechnique.cpp
new file mode 100644
index 0000000..8231bfb
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainTechnique.cpp
@@ -0,0 +1,343 @@
+#include <ossimPlanet/ossimPlanetTerrainTechnique.h>
+#include <ossimPlanet/ossimPlanetTerrainTile.h>
+#include <queue>
+#include <osg/Timer>
+#include <osg/Geometry>
+#if ((OSG_VERSION_INT)>182)
+#define USE_OLD_VBO_COMPILE 0
+#else
+#define USE_OLD_VBO_COMPILE 1
+#endif
+
+void ossimPlanetTerrainTechnique::CompileObjects::apply(osg::Drawable& drawable)
+{
+ osg::Geometry* geometry = drawable.asGeometry();
+ if(geometry)
+ {
+ osg::Geometry::ArrayList arrayList;
+ geometry->getArrayList(arrayList);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < arrayList.size();++idx)
+ {
+#if 0
+ if(arrayList[idx]->getVertexBufferObject())
+ {
+ arrayList[idx]->getVertexBufferObject()->compileBuffer(*_renderInfo.getState());
+ }
+#endif
+// if(arrayList[idx]->getVertexBufferObject())
+// {
+// osg::GLBufferObject* glBufferObj = arrayList[idx]->getVertexBufferObject()->getOrCreateGLBufferObject(_renderInfo.getState()->getContextID());
+// if(glBufferObj&&glBufferObj->isDirty())
+// {
+// glBufferObj->compileBuffer();
+// }
+ }
+ // }
+ }
+ osgUtil::GLObjectsVisitor::apply(drawable);
+}
+
+void ossimPlanetTerrainTechnique::CompileObjects::apply(osg::Node& node)
+{
+ if (node.getStateSet())
+ {
+ apply(*(node.getStateSet()));
+ }
+
+ traverse(node);
+}
+void ossimPlanetTerrainTechnique::CompileObjects::apply(osg::Geode& node)
+{
+ if (node.getStateSet())
+ {
+ apply(*(node.getStateSet()));
+ }
+ for(unsigned int i=0;i<node.getNumDrawables();++i)
+ {
+ osg::Drawable* drawable = node.getDrawable(i);
+ if (drawable)
+ {
+ apply(*drawable);
+ if (drawable->getStateSet())
+ {
+ apply(*(drawable->getStateSet()));
+ }
+ }
+ }
+
+ // now let's compile all buffer objects
+ //
+
+}
+
+void ossimPlanetTerrainTechnique::CompileObjects::apply(osg::StateSet& stateset)
+{
+ if (_stateSetAppliedSet.count(&stateset)!=0) return;
+ _stateSetAppliedSet.insert(&stateset);
+
+ if (_mode & COMPILE_STATE_ATTRIBUTES && _renderInfo.getState())
+ {
+ osg::StateSet::AttributeList& attributeList = stateset.getAttributeList();
+ for(osg::StateSet::AttributeList::const_iterator itr = attributeList.begin();
+ itr!=attributeList.end();
+ ++itr)
+ {
+ itr->second.first->compileGLObjects(*_renderInfo.getState());
+ }
+
+ for (unsigned i = 0;
+ i < stateset.getTextureAttributeList().size();
+ ++i)
+ {
+ const osg::Texture* texture
+ = dynamic_cast<const osg::Texture*>(stateset.getTextureAttribute(i,osg::StateAttribute::TEXTURE));
+ if (texture && (texture->getTextureParameterDirty(_renderInfo.getContextID())||(texture->getTextureObject(_renderInfo.getContextID())==0)))
+ {
+ texture->compileGLObjects(*_renderInfo.getState());
+ }
+ }
+ }
+ if (_mode & CHECK_BLACK_LISTED_MODES)
+ {
+ stateset.checkValidityOfAssociatedModes(*_renderInfo.getState());
+ }
+}
+
+ossimPlanetTerrainTechnique::ossimPlanetTerrainTechnique()
+:theTerrainTile(0)
+{
+ setThreadSafeRefUnref(true);
+}
+ossimPlanetTerrainTechnique::ossimPlanetTerrainTechnique(const ossimPlanetTerrainTechnique& src,
+ const osg::CopyOp& /* copyop */)
+:
+ theModel(src.theModel.get()), // this is just shared
+ theGrid(src.theGrid.get()), // this is just shared
+ theTerrainTile(0) // can't duplicate this
+{
+}
+
+ossimPlanetTerrainTechnique::~ossimPlanetTerrainTechnique()
+{
+}
+
+void ossimPlanetTerrainTechnique::setTerrainTile(ossimPlanetTerrainTile* tile)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theTerrainTileMutex);
+ theTerrainTile = tile;
+ if(theTerrainTile)
+ {
+ theTerrainTile->setCullCallback(new ossimPlanetTerrainTechnique::CullCallback());
+ }
+}
+
+void ossimPlanetTerrainTechnique::init(ossimPlanetTerrainTile* /* optionalParent */)
+{
+}
+
+void ossimPlanetTerrainTechnique::update(osgUtil::UpdateVisitor* uv)
+{
+ if (theTerrainTile) theTerrainTile->osg::Group::traverse(*uv);
+}
+
+void ossimPlanetTerrainTechnique::cull(osgUtil::CullVisitor* cv)
+{
+ if (theTerrainTile) theTerrainTile->osg::Group::traverse(*cv);
+}
+
+void ossimPlanetTerrainTechnique::traverse(osg::NodeVisitor& nv)
+{
+ if (!theTerrainTile) return;
+
+ // if app traversal update the frame count.
+ if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
+ {
+ osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv);
+ if (uv)
+ {
+ update(uv);
+ return;
+ }
+
+ }
+ else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
+ {
+ osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
+ if (cv)
+ {
+ cull(cv);
+ return;
+ }
+ }
+
+ // otherwise fallback to the Group::traverse()
+ theTerrainTile->osg::Group::traverse(nv);
+}
+
+bool ossimPlanetTerrainTechnique::isLeaf()const
+{
+ if(theTerrainTile)
+ {
+ return (theTerrainTile->getNumChildren() != 4);
+ }
+
+ return true;
+}
+
+bool ossimPlanetTerrainTechnique::areAllChildrenLeaves()const
+{
+ if(!theTerrainTile) return false;
+ if(theTerrainTile->getNumChildren()!=4) return false;
+ ossim_uint32 idx;
+ ossim_uint32 bounds = theTerrainTile->getNumChildren();
+ for(idx = 1; idx < bounds; ++idx)
+ {
+ const ossimPlanetTerrainTile* tile = dynamic_cast<const ossimPlanetTerrainTile*>(theTerrainTile->getChild(idx));
+ if(tile)
+ {
+ if(!tile->terrainTechnique()->isLeaf()) return false;
+ }
+ }
+
+ return true;
+}
+
+void ossimPlanetTerrainTechnique::vacantChildIds(TileIdList& ids)const
+{
+ if(!theTerrainTile)
+ {
+ return;
+ }
+ ossim_uint32 idx = 0;
+ const ossimPlanetTerrainTileId& srcId = theTerrainTile->tileId();
+ ossim_uint32 nextLevel = srcId.level()+1;
+ for(idx = 0; idx < 4; ++idx)
+ {
+ ossim_uint32 xOrigin=srcId.x()<<1;
+ ossim_uint32 yOrigin=srcId.y()<<1;
+ if(idx == 1)
+ {
+ ++xOrigin;
+ }
+ else if(idx == 2)
+ {
+ ++yOrigin;
+ }
+ else if(idx == 3)
+ {
+ ++xOrigin;
+ ++yOrigin;
+ }
+ ossimPlanetTerrainTileId tileId(srcId.face(),
+ nextLevel,
+ xOrigin,
+ yOrigin);
+ if(!theTerrainTile->child(tileId))
+ {
+ ids.push_back(tileId);
+ }
+ }
+}
+
+void ossimPlanetTerrainTechnique::merge()
+{
+ if(theTerrainTile)
+ {
+ // we really need to go through the sub tree and free each one or
+ // remove from parent
+ //
+ }
+}
+
+ossim_uint32 ossimPlanetTerrainTechnique::childIndex(const ossimPlanetTerrainTileId& tileId)const
+{
+ return (((tileId.y()&1)<<1)|
+ (tileId.x()&1));
+}
+
+void ossimPlanetTerrainTechnique::childTreePosition(const ossimPlanetTerrainTileId& tileId,
+ ossim_uint32& x, ossim_uint32& y)const
+{
+ x = tileId.x()&1;
+ y = tileId.y()&1;
+}
+
+void ossimPlanetTerrainTechnique::solveTextureMatrixMappingToParent(const ossimPlanetTerrainTileId& tileId,
+ osg::Matrixd& m)const
+{
+ switch(childIndex(tileId))
+ {
+ // during our split routine an index of 0 is the bottom left child and origin is 0,0 in parent
+ // we basically map local space 0 to 1 ro parent 0 to .5 for both x and y direction.
+ //
+ case 0:
+ {
+ m.set(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+ break;
+ }
+ // during our split routine an index of 1 is the bottom right child and origin is .5,0 in parent
+ // so we map local space 0 to 1 along x to .5 to 1 in parent for the x axis and we map
+ // y axis to 0 to .5
+ //
+ case 1:
+ {
+ m.set(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.5, 0.0, 0.0, 1.0);
+ break;
+ }
+
+ // during our split routine an index of 0 is the top left child and origin is 0,.5 in parent
+ // so we map local space 0 to 1 along x to 0 to .5 in parent for the x axis and we map
+ // y axis to .5 to 1
+ //
+ case 2:
+ {
+ m.set(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.5, 0.0, 1.0);
+ break;
+ }
+ // during our split routine an index of 0 is the top right child and origin is .5,.5 in parent
+ // so we map local space 0 to 1 along both axis to .5 to 1 in parent.
+ //
+ case 3:
+ {
+ m.set(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.5, 0.5, 0.0, 1.0);
+ break;
+ }
+ }
+}
+
+void ossimPlanetTerrainTechnique::solveTextureMatrixMappingToParent(const ossimPlanetTerrainTileId& startId,
+ const ossimPlanetTerrainTileId& endId,
+ osg::Matrixd& m)const
+{
+ m.makeIdentity();
+ if(startId.level() != 0)
+ {
+ if(startId.level() > endId.level())
+ {
+ osg::Matrixd mParent;
+ ossimPlanetTerrainTileId currentId = startId;
+ while(currentId.level() != endId.level())
+ {
+ solveTextureMatrixMappingToParent(currentId, mParent);
+ m*=mParent;
+ currentId.setId(currentId.face(),
+ currentId.level()-1,
+ currentId.x()>>1,
+ currentId.y()>>1);
+ }
+ }
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainTile.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainTile.cpp
new file mode 100644
index 0000000..412d7d3
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTerrainTile.cpp
@@ -0,0 +1,359 @@
+#include <ossimPlanet/ossimPlanetTerrainTile.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <OpenThreads/ScopedLock>
+#include <osg/io_utils>
+
+//#define OSGPLANET_ENABLE_ALLOCATION_COUNT
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static OpenThreads::Mutex objectCountMutex;
+static ossim_uint32 terrainTileCount = 0;
+#endif
+ossimPlanetTerrainTile::ossimPlanetTerrainTile()
+:osg::Group(),
+theTerrain(0),
+theCulledFlag(false),
+theFrameNumber(0),
+theTimeStamp(0.0),
+theSimTimeStamp(0.0)
+{
+ setDataVariance(osg::Object::DYNAMIC);
+ theSplitRequest = new ossimPlanetSplitRequest();
+ theTextureRequest = new ossimPlanetTextureRequest();
+ theElevationRequest = new ossimPlanetElevationRequest();
+ setThreadSafeRefUnref(true);
+ setUpdateCallback(new ossimPlanetTraverseCallback);
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ ++terrainTileCount;
+ std::cout << "ossimPlanetTerrainTile count = " << terrainTileCount << std::endl;
+#endif
+}
+
+ossimPlanetTerrainTile::ossimPlanetTerrainTile(const ossimPlanetTerrainTileId& value)
+:osg::Group(),
+theId(value),
+theTerrain(0),
+theCulledFlag(false),
+theFrameNumber(0),
+theTimeStamp(0.0),
+theSimTimeStamp(0.0)
+{
+ setDataVariance(osg::Object::DYNAMIC);
+ theSplitRequest = new ossimPlanetSplitRequest();
+ theTextureRequest = new ossimPlanetTextureRequest();
+ theElevationRequest = new ossimPlanetElevationRequest();
+
+ setUpdateCallback(new ossimPlanetTraverseCallback);
+ setThreadSafeRefUnref(true);
+ //setCullingActive(false); // we will do our own culling
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ ++terrainTileCount;
+ std::cout << "ossimPlanetTerrainTile count = " << terrainTileCount << std::endl;
+#endif
+}
+ossimPlanetTerrainTile::~ossimPlanetTerrainTile()
+{
+ if(theTerrain)
+ {
+ theTerrain->unregisterTile(this);
+ }
+ setCullCallback(0);
+ setTerrain(0);
+ theTerrainTechnique->setTerrainTile(0);
+ theTerrainTechnique = 0;
+ theGrid = 0;
+ theElevationLayer = 0;
+ theImageLayers.clear();
+ theTerrain = 0;
+ theSplitRequest = 0;
+ theTextureRequest = 0;
+ theElevationRequest = 0;
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ --terrainTileCount;
+ std::cout << "ossimPlanetTerrainTile count = " << terrainTileCount << std::endl;
+#endif
+}
+
+void ossimPlanetTerrainTile::init(ossimPlanetTerrainTile* optionalParentOverride)
+{
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->init(optionalParentOverride);
+ }
+}
+
+void ossimPlanetTerrainTile::traverse(osg::NodeVisitor& nv)
+{
+ if(!theTerrain)
+ {
+ setTerrain(ossimPlanetTerrain::findTerrain(nv.getNodePath()));
+ }
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->traverse(nv);
+ }
+ else
+ {
+ osg::Group::traverse(nv);
+ }
+}
+void ossimPlanetTerrainTile::setTerrainTechnique(ossimPlanetTerrainTechnique* terrainTechnique)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theTerrainTechnique = terrainTechnique;
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->setTerrainTile(this);
+ }
+}
+
+void ossimPlanetTerrainTile::copyCommonParameters(ossimPlanetTerrainTile* src)
+{
+ if(src)
+ {
+ setTerrain(src->terrain());
+ }
+}
+
+void ossimPlanetTerrainTile::setTileId(const ossimPlanetTerrainTileId& value)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theId = value;
+}
+
+void ossimPlanetTerrainTile::setTerrain(ossimPlanetTerrain* value)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theTerrain)
+ {
+ theTerrain->unregisterTile(this);
+ }
+ theTerrain = value;
+ if(theTerrain)
+ {
+ theTerrainTechnique = theTerrain->newTechnique();
+ theTerrainTechnique->theTerrainTile = this;
+ theGrid = theTerrain->grid();
+ theTerrain->registerTile(this);
+
+ resetImageLayers();
+ resetElevationLayer();
+ }
+}
+
+ossimPlanetTerrain* ossimPlanetTerrainTile::terrain()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theTerrain;
+}
+
+const ossimPlanetTerrain* ossimPlanetTerrainTile::terrain()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theTerrain;
+}
+
+void ossimPlanetTerrainTile::resetImageLayers()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ ossim_uint32 idx;
+ if(numberOfImageLayers()!= theTerrain->numberOfTextureLayers())
+ {
+ setNumberOfImageLayers(theTerrain->numberOfTextureLayers());
+ }
+ for(idx = 0; idx < theImageLayers.size(); ++idx)
+ {
+ if(!theImageLayers[idx].valid())
+ {
+ theImageLayers[idx] = new ossimPlanetTerrainImageLayer();
+ }
+ theImageLayers[idx]->setImage(0);
+ }
+}
+
+void ossimPlanetTerrainTile::resetElevationLayer()
+{
+ if(!elevationLayer())
+ {
+ theElevationLayer = new ossimPlanetTerrainImageLayer();
+ }
+ //theElevationLayer->setRowsColumns(9,9);
+ theElevationLayer->setImage(0);
+}
+
+void ossimPlanetTerrainTile::setNumberOfImageLayers(ossim_uint32 n)
+{
+
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+
+ if(n==0)
+ {
+ theImageLayers.clear();
+ }
+ else
+ {
+ theImageLayers.resize(n);
+ }
+}
+
+ossim_uint32 ossimPlanetTerrainTile::numberOfImageLayers()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return (ossim_uint32)theImageLayers.size();
+}
+
+bool ossimPlanetTerrainTile::imageLayersDirty()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theImageLayers.size();++idx)
+ {
+ if(theImageLayers[idx].get())
+ {
+ if(theImageLayers[idx]->isDirty())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+ossimPlanetTerrainImageLayer* ossimPlanetTerrainTile::imageLayer(ossim_uint32 idx)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+
+ ossimPlanetTerrainImageLayer* result = 0;
+ if(idx <theImageLayers.size())
+ {
+ result = theImageLayers[idx].get();
+ }
+
+ return result;
+}
+
+ossimPlanetTerrainImageLayer* ossimPlanetTerrainTile::elevationLayer()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theElevationLayer.get();
+}
+
+ossim_int32 ossimPlanetTerrainTile::indexOfChild(const ossimPlanetTerrainTileId& id)
+{
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = getNumChildren();
+ for(idx = 0; idx < bound;++idx)
+ {
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(getChild(idx));
+ if(tile&&(tile->tileId()==id))
+ {
+ return (ossim_int32)idx;
+ }
+ }
+ return -1;
+}
+
+ossimPlanetTerrainTile* ossimPlanetTerrainTile::child(const ossimPlanetTerrainTileId& id)
+{
+ ossim_uint32 idx = 0;
+ ossim_uint32 bound = getNumChildren();
+ for(idx = 0; idx < bound;++idx)
+ {
+ ossimPlanetTerrainTile* tile = dynamic_cast<ossimPlanetTerrainTile*>(getChild(idx));
+ if(tile&&(tile->tileId()==id))
+ {
+ return tile;
+ }
+ }
+ return 0;
+
+}
+
+void ossimPlanetTerrainTile::cancelAllOperations()
+{
+ theElevationRequest->cancel();
+ theSplitRequest->cancel();
+ theTextureRequest->cancel();
+}
+
+bool ossimPlanetTerrainTile::hasActiveOperations()const
+{
+ return ((theElevationRequest->referenceCount() > 1)||
+ (theSplitRequest->referenceCount() > 1)||
+ (theTextureRequest->referenceCount() > 1));
+}
+
+ossimPlanetTerrainTile* ossimPlanetTerrainTile::parentTile()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(getNumParents() < 1) return 0;
+ return dynamic_cast<ossimPlanetTerrainTile*>(getParent(0));
+}
+
+const ossimPlanetTerrainTile* ossimPlanetTerrainTile::parentTile()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(getNumParents() < 1) return 0;
+ return dynamic_cast<const ossimPlanetTerrainTile*>(getParent(0));
+}
+
+void ossimPlanetTerrainTile::vacantChildIds(ossimPlanetTerrainTechnique::TileIdList& ids)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->vacantChildIds(ids);
+ }
+}
+
+void ossimPlanetTerrainTile::merge()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->merge();
+ }
+ terrain()->setRedrawFlag(true);
+}
+
+osg::BoundingSphere ossimPlanetTerrainTile::computeBound() const
+{
+ if(theTerrainTechnique.valid())
+ {
+ return theTerrainTechnique->computeBound();
+ }
+ return osg::BoundingSphere(osg::Vec3d(0,0,0), -1);
+}
+
+void ossimPlanetTerrainTile::setCulledFlag(bool culled)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theCulledFlag = culled;
+}
+
+bool ossimPlanetTerrainTile::culledFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theCulledFlag;
+}
+void ossimPlanetTerrainTile::releaseGLObjects(osg::State* state)
+{
+ osg::Group::releaseGLObjects(state);
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->releaseGLObjects(state);
+ }
+}
+
+void ossimPlanetTerrainTile::childInserted(unsigned int pos)
+{
+ if(theTerrainTechnique.valid())
+ {
+ theTerrainTechnique->childAdded(pos);
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTexture2D.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTexture2D.cpp
new file mode 100644
index 0000000..6ebf626
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTexture2D.cpp
@@ -0,0 +1,83 @@
+#include <iostream>
+#include <ossimPlanet/ossimPlanetTexture2D.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <OpenThreads/ScopedLock>
+#include <osg/DisplaySettings>
+//#define OSGPLANET_ENABLE_ALLOCATION_COUNT
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+static OpenThreads::Mutex objectCountMutex;
+static ossim_uint32 textureCount = 0;
+#endif
+
+ossimPlanetTexture2D::ossimPlanetTexture2D(const ossimPlanetTerrainTileId& id)
+
+ :osg::Texture2D(),
+ theTileId(id)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ ++textureCount;
+ std::cout << "ossimPlanetTexture2D count = " << textureCount << "\n";
+#endif
+}
+
+ossimPlanetTexture2D::ossimPlanetTexture2D(osg::Image* image,
+ const ossimPlanetTerrainTileId& id)
+ :osg::Texture2D(image),
+ theTileId(id)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ ++textureCount;
+ std::cout << "ossimPlanetTexture2D count = " << textureCount << "\n";
+#endif
+}
+ossimPlanetTexture2D::ossimPlanetTexture2D(ossimPlanetImage* image)
+:osg::Texture2D(image),
+theTileId(image?image->tileId():ossimPlanetTerrainTileId())
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ ++textureCount;
+ std::cout << "ossimPlanetTexture2D count = " << textureCount << "\n";
+#endif
+}
+
+ossimPlanetTexture2D::ossimPlanetTexture2D(const ossimPlanetTexture2D& text,const osg::CopyOp& copyop)
+ :osg::Texture2D(text, copyop)
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ ++textureCount;
+ std::cout << "ossimPlanetTexture2D count = " << textureCount << "\n";
+#endif
+}
+
+ossimPlanetTexture2D::~ossimPlanetTexture2D()
+{
+#ifdef OSGPLANET_ENABLE_ALLOCATION_COUNT
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(objectCountMutex);
+ --textureCount;
+ std::cout << "ossimPlanetTexture2D count = " << textureCount << "\n";
+#endif
+}
+
+void ossimPlanetTexture2D::setImage(ossimPlanetImage* image)
+{
+ if(image)
+ {
+ setId(image->tileId());
+ }
+
+ osg::Texture2D::setImage(image);
+}
+
+void ossimPlanetTexture2D::setId(const ossimPlanetTerrainTileId& id)
+{
+ theTileId = id;
+}
+
+const ossimPlanetTerrainTileId& ossimPlanetTexture2D::tileId()const
+{
+ return theTileId;
+}
\ No newline at end of file
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayer.cpp
new file mode 100644
index 0000000..01ba201
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayer.cpp
@@ -0,0 +1,1641 @@
+#include <ossimPlanet/ossimPlanetTextureLayer.h>
+#include <algorithm>
+#include <osg/Vec2d>
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetIdManager.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimLine.h>
+#include <algorithm>
+
+ossimPlanetTextureLayer::ossimPlanetTextureLayer()
+ :osg::Referenced(),
+ theName(""),
+ theDescription("ossimPlanetTextureLayer"),
+ theId(),
+ theEnableFlag(true),
+ theTransparentColorFlag(false),
+ theTransparentColorVector(3),
+// theFilterType("bilinear"),
+ theFilterType("bilinear"),
+ theDirtyExtentsFlag(true),
+ theDirtyStatsFlag(true),
+ theStateCode(ossimPlanetTextureLayer_VALID)
+
+{
+// theLookAt = new ossimPlanetLookAt();
+// theLookAt->setRange(7000000);
+ theExtents = new ossimPlanetExtents();
+ theStats = new ossimPlanetTextureLayer::Stats();
+ theTransparentColorVector[0] = 0;
+ theTransparentColorVector[1] = 0;
+ theTransparentColorVector[2] = 0;
+
+ theBrightness = 0.0;
+ theContrast = 1.0;
+ theOpacity = 1.0;
+}
+
+ossimPlanetTextureLayer::ossimPlanetTextureLayer(const ossimPlanetTextureLayer& src)
+ :osg::Referenced(),
+ theName(src.theName),
+ theDescription(src.theDescription),
+ theId(src.theId),
+ theExtents(src.theExtents->clone()),
+ theEnableFlag(src.theEnableFlag),
+ theTransparentColorFlag(src.theTransparentColorFlag),
+ theTransparentColorVector(src.theTransparentColorVector),
+ theFilterType(src.theFilterType),
+ theDirtyExtentsFlag(src.theDirtyExtentsFlag),
+ theDirtyStatsFlag(src.theDirtyStatsFlag),
+ theStateCode(src.theStateCode),
+ theBrightness(src.theBrightness),
+ theContrast(src.theContrast),
+ theOpacity(src.theOpacity)
+{
+// std::cout << "ossimPlanetTextureLayer::ossimPlanetTextureLayer ERROR: NEED TO DO PARENT LIST COPY!!!!!" << std::endl;
+}
+
+ossimPlanetTextureLayer::~ossimPlanetTextureLayer()
+{
+
+}
+
+ossimString ossimPlanetTextureLayer::getClassName()const
+{
+ return "ossimPlanetTextureLayer";
+}
+
+void ossimPlanetTextureLayer::dirtyExtents()
+{
+ // already dirty
+ if(theDirtyExtentsFlag) return;
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theParentListMutex);
+ theDirtyExtentsFlag = true;
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ theParentList[idx]->dirtyExtents();
+ }
+}
+
+void ossimPlanetTextureLayer::setDirtyExtentsFlag(bool flag)
+{
+ theDirtyExtentsFlag = flag;
+}
+
+void ossimPlanetTextureLayer::dirtyStats()
+{
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theParentListMutex);
+ theDirtyStatsFlag = true;
+
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ theParentList[idx]->dirtyStats();
+ }
+}
+
+void ossimPlanetTextureLayer::addBytesTransferredStat(ossim_uint64 bytesTransferred)const
+{
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theParentListMutex);
+ theStats->setBytesTransferred(theStats->bytesTransferred() + bytesTransferred);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ theParentList[idx]->addBytesTransferredStat(bytesTransferred);
+ }
+}
+
+void ossimPlanetTextureLayer::clearState(ossimPlanetTextureLayerStateCode stateCode)const
+{
+ ossim_uint32 temp = (ossim_uint32)theStateCode;
+
+ temp &= (~((ossim_uint32)stateCode));
+
+ theStateCode = (ossimPlanetTextureLayerStateCode)temp;
+}
+
+void ossimPlanetTextureLayer::setState(ossimPlanetTextureLayerStateCode stateCode)const
+{
+ theStateCode = (ossimPlanetTextureLayerStateCode)(theStateCode|stateCode);
+ notifyPropertyChanged("stateCode", this);
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetTextureLayer::getStateCode()const
+{
+ return theStateCode;
+}
+
+bool ossimPlanetTextureLayer::isStateSet(ossimPlanetTextureLayerStateCode stateCode)const
+{
+ return (theStateCode & stateCode);
+}
+
+const osg::ref_ptr<ossimPlanetExtents> ossimPlanetTextureLayer::getExtents()const
+{
+ return theExtents.get();
+}
+
+osg::ref_ptr<ossimPlanetExtents> ossimPlanetTextureLayer::getExtents()
+{
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+
+ return theExtents.get();
+}
+
+
+
+const osg::ref_ptr<ossimPlanetTextureLayer::Stats> ossimPlanetTextureLayer::getStats()const
+{
+ if(theDirtyStatsFlag)
+ {
+ updateStats();
+ theDirtyStatsFlag = false;
+ }
+ return theStats;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer::Stats> ossimPlanetTextureLayer::getStats()
+{
+ if(theDirtyStatsFlag)
+ {
+ updateStats();
+ theDirtyStatsFlag = false;
+ }
+ return theStats;
+}
+
+
+void ossimPlanetTextureLayer::setExtents(osg::ref_ptr<ossimPlanetExtents> extents)
+{
+ theExtents = extents;
+ dirtyExtents();
+ theDirtyExtentsFlag = false;
+}
+
+void ossimPlanetTextureLayer::getDateRange(ossimDate& minDate,
+ ossimDate& maxDate)const
+{
+ minDate = theExtents->getMinDate();
+ maxDate = theExtents->getMaxDate();
+}
+
+const osg::ref_ptr<ossimPlanetLookAt> ossimPlanetTextureLayer::getLookAt()const
+{
+ return theLookAt.get();
+}
+
+void ossimPlanetTextureLayer::setLookAt(osg::ref_ptr<ossimPlanetLookAt> lookAt)
+{
+ theLookAt = lookAt.get();
+}
+
+double ossimPlanetTextureLayer::getApproximateHypotneusLength()const
+{
+ return ((osg::Vec2d(theExtents->getMaxLat(),
+ theExtents->getMinLon())-
+ osg::Vec2d(theExtents->getMinLat(),
+ theExtents->getMaxLon())).length() *
+ ossimGpt().metersPerDegree().x);
+}
+
+void ossimPlanetTextureLayer::getCenterLatLonLength(double& centerLat,
+ double& centerLon,
+ double& length)const
+{
+ length = ((osg::Vec2d(theExtents->getMaxLat(), theExtents->getMinLon())-
+ osg::Vec2d(theExtents->getMinLat(), theExtents->getMaxLon())).length() *
+ ossimGpt().metersPerDegree().x);
+ centerLat = (theExtents->getMinLat()+theExtents->getMaxLat())*.5;
+ centerLon = (theExtents->getMinLon()+theExtents->getMaxLon())*.5;
+}
+
+ossimPlanetTextureLayerGroup* ossimPlanetTextureLayer::asGroup()
+{
+ return 0;
+}
+
+const ossimPlanetTextureLayerGroup* ossimPlanetTextureLayer::asGroup()const
+{
+ return 0;
+}
+
+ossimPlanetTextureLayerGroup* ossimPlanetTextureLayer::getParent(ossim_uint32 idx)
+{
+ return parent(idx);
+}
+
+const ossimPlanetTextureLayerGroup* ossimPlanetTextureLayer::getParent(ossim_uint32 idx)const
+{
+ return parent(idx);
+}
+
+ossimPlanetTextureLayerGroup* ossimPlanetTextureLayer::parent(ossim_uint32 idx)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ if(idx < theParentList.size())
+ {
+ return theParentList[idx];
+ }
+
+ return 0;
+}
+
+const ossimPlanetTextureLayerGroup* ossimPlanetTextureLayer::parent(ossim_uint32 idx)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+
+ if(idx < theParentList.size())
+ {
+ return theParentList[idx];
+ }
+
+ return 0;
+}
+
+bool ossimPlanetTextureLayer::hasParent(ossimPlanetTextureLayerGroup* parent)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ if(theParentList[idx] == parent)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ossimPlanetTextureLayer::addParent(ossimPlanetTextureLayerGroup* parent)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ if(theParentList[idx] == parent)
+ {
+ return;
+ }
+ }
+
+ theParentList.push_back(parent);
+}
+
+void ossimPlanetTextureLayer::removeParent(ossimPlanetTextureLayerGroup* parent)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ if(theParentList[idx] == parent)
+ {
+ theParentList.erase(theParentList.begin()+idx);
+ }
+ }
+}
+
+void ossimPlanetTextureLayer::detachFromParents()
+{
+ ossim_uint32 idx = 0;
+
+ theMutex.lock();
+ ossimPlanetTextureLayerParentList parentList = theParentList;
+ theParentList.clear();
+ theMutex.unlock();
+ for(idx = 0; idx < parentList.size(); ++idx)
+ {
+ parentList[idx]->removeLayer(this);
+ }
+}
+
+const ossimString& ossimPlanetTextureLayer::id()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theId;
+}
+
+void ossimPlanetTextureLayer::setId(const ossimString& id)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theId = id;
+ }
+ notifyPropertyChanged("id", this);
+}
+
+void ossimPlanetTextureLayer::setEnableFlag(bool flag)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theEnableFlag = flag;
+ }
+ notifyPropertyChanged("enableFlag", this);
+}
+
+bool ossimPlanetTextureLayer::getEnableFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theEnableFlag;
+}
+
+bool ossimPlanetTextureLayer::enableFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theEnableFlag;
+}
+
+void ossimPlanetTextureLayer::setName(const ossimString& name)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theName = name;
+ }
+ notifyPropertyChanged("name", this);
+}
+
+const ossimString& ossimPlanetTextureLayer::getName()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theName;
+}
+
+const ossimString& ossimPlanetTextureLayer::name()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theName;
+}
+
+void ossimPlanetTextureLayer::setDescription(const ossimString& description)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theDescription = description;
+ }
+ notifyPropertyChanged("description", this);
+}
+
+const ossimString& ossimPlanetTextureLayer::getDescription()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theDescription;
+}
+
+const ossimString& ossimPlanetTextureLayer::description()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theDescription;
+}
+
+bool ossimPlanetTextureLayer::getTransparentColorFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theTransparentColorFlag;
+}
+
+void ossimPlanetTextureLayer::setTransparentColorFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theTransparentColorFlag = flag;
+}
+
+const ossimPlanetTextureLayer::TransparentColorType& ossimPlanetTextureLayer::getTransparentColor()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theTransparentColorVector;
+}
+
+void ossimPlanetTextureLayer::setTransparentColor(unsigned int r,
+ unsigned int g,
+ unsigned int b)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theTransparentColorVector[0] = r;
+ theTransparentColorVector[1] = g;
+ theTransparentColorVector[2] = b;
+}
+
+ossimPlanetImage* ossimPlanetTextureLayer::applyBrightnessContrast(ossimPlanetImage* image, bool duplicateFlag)const
+{
+ ossimPlanetImage* result = image;
+ if(((brightness() != 0.0)||
+ (contrast() != 1.0))&&image)
+ {
+ if(duplicateFlag)
+ {
+ result = new ossimPlanetImage(*image);
+ }
+ result->applyBrightnessContrast(brightness(), contrast());
+ }
+
+ return result;
+}
+
+/*
+void ossimPlanetTextureLayer::mergeImage(ossimPlanetImage* result,
+ const ossimPlanetImage* source,
+ ossim_float32 sourceOpacity)const
+{
+ if(!result || !source) return;
+
+ unsigned int w = result->s();
+ unsigned int h = result->t();
+ unsigned int area = w*h;
+ unsigned int idx = 0;
+
+ unsigned char* destBuf = result->data();
+ const unsigned char* srcBuf = source->data();
+
+ if(sourceOpacity == 1.0)
+ {
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(srcBuf[3] == 255)
+ {
+ destBuf[0] = srcBuf[0];
+ destBuf[1] = srcBuf[1];
+ destBuf[2] = srcBuf[2];
+ destBuf[3] = 255;
+ }
+ else if(srcBuf[3] > 0)
+ {
+ float normalizedValue = (srcBuf[3]/255.0);
+
+ destBuf[0] = static_cast<unsigned char>(destBuf[0]*(1-normalizedValue) + srcBuf[0]*normalizedValue);
+ destBuf[1] = static_cast<unsigned char>(destBuf[1]*(1-normalizedValue) + srcBuf[1]*normalizedValue);
+ destBuf[2] = static_cast<unsigned char>(destBuf[2]*(1-normalizedValue) + srcBuf[2]*normalizedValue);
+ destBuf[3] = 255;
+ }
+ destBuf += 4;
+ srcBuf += 4;
+ }
+ }
+ else
+ {
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(srcBuf[3] ==255)
+ {
+ destBuf[0] = srcBuf[0]*(1-sourceOpacity) + destBuf[0]*(sourceOpacity);
+ destBuf[1] = srcBuf[1]*(1-sourceOpacity) + destBuf[1]*(sourceOpacity);
+ destBuf[2] = srcBuf[2]*(1-sourceOpacity) + destBuf[2]*(sourceOpacity);
+ destBuf[3] = 255;
+ }
+ else if(srcBuf[3] > 0)
+ {
+ float normalizedValue = (srcBuf[3]/255.0)*sourceOpacity;
+
+ destBuf[0] = static_cast<unsigned char>(destBuf[0]*(1-normalizedValue) + srcBuf[0]*normalizedValue);
+ destBuf[1] = static_cast<unsigned char>(destBuf[1]*(1-normalizedValue) + srcBuf[1]*normalizedValue);
+ destBuf[2] = static_cast<unsigned char>(destBuf[2]*(1-normalizedValue) + srcBuf[2]*normalizedValue);
+ destBuf[3] = 255;
+ }
+ destBuf += 4;
+ srcBuf += 4;
+ }
+ }
+}
+*/
+void ossimPlanetTextureLayer::mergeImage(ossimPlanetImage* result,
+ const ossimPlanetImage* source,
+ ossim_float32 sourceOpacity)const
+{
+ if(!result || !source) return;
+
+ unsigned int w = result->s();
+ unsigned int h = result->t();
+ unsigned int area = w*h;
+ unsigned int idx = 0;
+
+ unsigned char* destBuf = result->data();
+ const unsigned char* srcBuf = source->data();
+
+ if(sourceOpacity == 1.0)
+ {
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(srcBuf[3] == 255)
+ {
+ destBuf[0] = srcBuf[0];
+ destBuf[1] = srcBuf[1];
+ destBuf[2] = srcBuf[2];
+ destBuf[3] = 255;
+ }
+ else if(srcBuf[3] > 0)
+ {
+ float alpha = 255 - (1 - srcBuf[3]/255.0) * (255-destBuf[3]);
+ float normalizedValue = srcBuf[3]/alpha;
+
+ destBuf[0] = static_cast<unsigned char>(srcBuf[0]*normalizedValue + destBuf[0]*(1-normalizedValue));
+ destBuf[1] = static_cast<unsigned char>(srcBuf[1]*normalizedValue + destBuf[1]*(1-normalizedValue));
+ destBuf[2] = static_cast<unsigned char>(srcBuf[2]*normalizedValue + destBuf[2]*(1-normalizedValue));
+ destBuf[3] = static_cast<unsigned char>(alpha);
+ }
+ destBuf += 4;
+ srcBuf += 4;
+ }
+ }
+ else if(sourceOpacity > 0.0)
+ {
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(srcBuf[3] > 0)
+ {
+ float alpha = 255 - (1 - srcBuf[3]* sourceOpacity /255.0) * (255-destBuf[3]);
+ float normalizedValue = srcBuf[3]/alpha;
+
+ destBuf[0] = static_cast<unsigned char>(srcBuf[0]*normalizedValue + destBuf[0]*(1-normalizedValue));
+ destBuf[1] = static_cast<unsigned char>(srcBuf[1]*normalizedValue + destBuf[1]*(1-normalizedValue));
+ destBuf[2] = static_cast<unsigned char>(srcBuf[2]*normalizedValue + destBuf[2]*(1-normalizedValue));
+ destBuf[3] = static_cast<unsigned char>(alpha);
+ }
+
+ destBuf += 4;
+ srcBuf += 4;
+ }
+ }
+}
+
+bool ossimPlanetTextureLayer::insertAlpha(osg::ref_ptr<ossimPlanetImage> texture,
+ float initialAlphaValue)const
+{
+ GLint internalFormat = texture->getInternalTextureFormat();
+ unsigned int w = texture->s();
+ unsigned int h = texture->t();
+ unsigned int area = w*h;
+ unsigned char* data = texture->data();
+ unsigned char alpha = static_cast<unsigned char>(initialAlphaValue*255.0);
+ if((internalFormat != GL_RGB)&&
+ (internalFormat != GL_RGBA))
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetTextureArchive::insertAlpha: ERROR image not an RGB image format" << std::endl;
+
+ return false;
+ }
+
+ if(internalFormat == GL_RGB)
+ {
+ unsigned char* newData = new unsigned char[area*4];
+ unsigned char* newDataPtr = newData;
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ newDataPtr[0] = data[0];
+ newDataPtr[1] = data[1];
+ newDataPtr[2] = data[2];
+ newDataPtr[3] = alpha;
+ newDataPtr+=4;
+ data+=3;
+ }
+ texture->setImage(w, h, 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ newData,
+ osg::Image::USE_NEW_DELETE);
+
+ }
+ else // copy over existing alpha since already have alpha
+ {
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ data[3] = alpha;
+ data+=4;
+ }
+
+ }
+ texture->dirty();
+
+ return true;
+}
+
+bool ossimPlanetTextureLayer::insertAlpha(osg::ref_ptr<ossimPlanetImage> texture)const
+{
+ if(!theTransparentColorFlag)
+ {
+ return insertAlpha(texture, 1.0);
+ }
+
+ GLint internalFormat = texture->getInternalTextureFormat();
+ unsigned int w = texture->s();
+ unsigned int h = texture->t();
+ unsigned int area = w*h;
+ unsigned char* data = texture->data();
+ if((internalFormat != GL_RGB)&&
+ (internalFormat != GL_RGBA))
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetTextureArchive::insertAlpha: ERROR image not an RGB image format" << std::endl;
+
+ return false;
+ }
+ const unsigned char* transparentColor = &theTransparentColorVector.front();
+
+ if(internalFormat == GL_RGB)
+ {
+ unsigned char* newData = new unsigned char[area*4];
+ unsigned char* newDataPtr = newData;
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ newDataPtr[0] = data[0];
+ newDataPtr[1] = data[1];
+ newDataPtr[2] = data[2];
+ if((newDataPtr[0] == transparentColor[0])&&
+ (newDataPtr[1] == transparentColor[1])&&
+ (newDataPtr[2] == transparentColor[2]))
+ {
+ newDataPtr[3] = 0;
+ }
+ else
+ {
+ newDataPtr[3] = 255;
+ }
+ newDataPtr+=4;
+ data+=3;
+ }
+ texture->setImage(w, h, 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ newData,
+ osg::Image::USE_NEW_DELETE);
+ }
+ else // copy over existing alpha since already have alpha
+ {
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ if((data[0] == transparentColor[0])&&
+ (data[1] == transparentColor[1])&&
+ (data[2] == transparentColor[2]))
+ {
+ data[3] = 0;
+ }
+ data+=4;
+ }
+
+ }
+ texture->dirty();
+ texture->setPixelStatus();
+
+ return true;
+}
+
+void ossimPlanetTextureLayer::addTransparent(osg::ref_ptr<ossimPlanetImage> texture)const
+{
+ if(!theTransparentColorFlag) return;
+ const unsigned char* transparentColor = &theTransparentColorVector.front();
+ GLint internalFormat = texture->getInternalTextureFormat();
+ unsigned int w = texture->s();
+ unsigned int h = texture->t();
+ unsigned int area = w*h;
+ unsigned char* data = texture->data();
+ if((internalFormat != GL_RGBA))
+ {
+ ossimNotify(ossimNotifyLevel_WARN) << "ossimPlanetTextureArchive::addTransparent: ERROR image not an RGBA image format" << std::endl;
+
+ return;
+ }
+ for(unsigned int idx = 0; idx < area;++idx)
+ {
+ if((data[0] == transparentColor[0])&&
+ (data[1] == transparentColor[1])&&
+ (data[2] == transparentColor[2]))
+ {
+ data[3] = 0;
+ }
+ data+=4;
+ }
+ texture->dirty();
+}
+
+
+
+void ossimPlanetTextureLayer::setFilterType(const ossimString& filterType)
+{
+ theFilterType = filterType;
+}
+
+const ossimString& ossimPlanetTextureLayer::getFilterTypeAsString()const
+{
+ return theFilterType;
+}
+
+// void ossimPlanetTextureLayer::addCallback(osg::ref_ptr<ossimPlanetTextureLayer::Callback> callback)
+// {
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackMutex);
+
+// ossimPlanetTextureLayer::CallbackList::iterator iter = std::find(theCallbackList.begin(), theCallbackList.end(), callback);
+// if(iter == theCallbackList.end())
+// {
+// theCallbackList.push_back(callback);
+// }
+// }
+
+// void ossimPlanetTextureLayer::removeCallback(osg::ref_ptr<ossimPlanetTextureLayer::Callback> callback)
+// {
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackMutex);
+// ossimPlanetTextureLayer::CallbackList::iterator iter = std::find(theCallbackList.begin(), theCallbackList.end(), callback);
+// if(iter != theCallbackList.end())
+// {
+// theCallbackList.erase(iter);
+// }
+// }
+
+
+void ossimPlanetTextureLayer::notifyRefreshExtent(osg::ref_ptr<ossimPlanetExtents> extent)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->refreshExtent(extent);
+ }
+ }
+}
+
+void ossimPlanetTextureLayer::notifyLayerAdded(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->layerAdded(layer);
+ }
+ }
+}
+
+
+void ossimPlanetTextureLayer::notifyLayerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ osg::ref_ptr<ossimPlanetTextureLayer> parent)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->layerRemoved(layer, parent);
+ }
+ }
+}
+
+
+void ossimPlanetTextureLayer::notifyPropertyChanged(const ossimString& name,
+ const ossimPlanetTextureLayer* layer)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx;
+ for(idx =0; idx < theCallbackList.size(); ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->propertyChanged(name, layer);
+ }
+ }
+}
+
+void ossimPlanetTextureLayer::resetLookAt()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ double lat, lon, len;
+ getCenterLatLonLength(lat, lon, len);
+
+ theLookAt = new ossimPlanetLookAt;
+
+ theLookAt->setLat(lat);
+ theLookAt->setLon(lon);
+ theLookAt->setRange(len);
+}
+
+void ossimPlanetTextureLayer::convertToOsg(ossimImageData* data,
+ ossimPlanetImage* image)const
+{
+ if(data->getScalarType() == OSSIM_UINT8)
+ {
+ ossim_uint32 w = data->getWidth();
+ ossim_uint32 h = data->getHeight();
+ ossim_uint32 area = w*h;
+ ossim_uint32 idx = 0;
+ unsigned char* buf = new unsigned char[area*4];
+ unsigned char* bufPtr = buf;
+
+ unsigned char* b1 = NULL;
+ unsigned char* b2 = NULL;
+ unsigned char* b3 = NULL;
+ unsigned char np1 = 0;
+ unsigned char np2 = 0;
+ unsigned char np3 = 0;
+
+ if(data->getNumberOfBands()< 3)
+ {
+ b1 = (unsigned char*)data->getBuf(0);
+ b2 = (unsigned char*)data->getBuf(0);
+ b3 = (unsigned char*)data->getBuf(0);
+ np1 = (unsigned char)data->getNullPix(0);
+ np2 = (unsigned char)data->getNullPix(0);
+ np3 = (unsigned char)data->getNullPix(0);
+ }
+ else
+ {
+ b1 = (unsigned char*)data->getBuf(0);
+ b2 = (unsigned char*)data->getBuf(1);
+ b3 = (unsigned char*)data->getBuf(2);
+ np1 = (unsigned char)data->getNullPix(0);
+ np2 = (unsigned char)data->getNullPix(1);
+ np3 = (unsigned char)data->getNullPix(2);
+ }
+
+ if(!theTransparentColorFlag)
+ {
+ for(idx = 0; idx < area; ++idx)
+ {
+ if((*b1==np1)&&
+ (*b2==np2)&&
+ (*b3==np3))
+ {
+ bufPtr[3] = 0;
+ }
+ else
+ {
+ bufPtr[3] = 255;
+ }
+ bufPtr[0] = *b1;
+ bufPtr[1] = *b2;
+ bufPtr[2] = *b3;
+ bufPtr +=4;
+ ++b1;
+ ++b2;
+ ++b3;
+ }
+ }
+ else
+ {
+ const unsigned char* transparentColor = &theTransparentColorVector.front();
+ for(idx = 0; idx < area; ++idx)
+ {
+ if(((*b1==np1)&&
+ (*b2==np2)&&
+ (*b3==np3))||
+ ((*b1==transparentColor[0])&&
+ (*b2==transparentColor[1])&&
+ (*b3==transparentColor[2])))
+ {
+ bufPtr[3] = 0;
+ }
+ else
+ {
+ bufPtr[3] = 255;
+ }
+ bufPtr[0] = *b1;
+ bufPtr[1] = *b2;
+ bufPtr[2] = *b3;
+ bufPtr +=4;
+ ++b1;
+ ++b2;
+ ++b3;
+ }
+
+ }
+
+ image->setImage(w,
+ h,
+ 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ buf,
+ osg::Image::USE_NEW_DELETE);
+// image->flipVertical();
+ image->setPixelStatus();
+ }
+}
+
+void ossimPlanetTextureLayer::convertToOsg(ossimImageData* data,
+ ossimPlanetImage* image,
+ const osg::Vec2d& ulInput,
+ const osg::Vec2d& /*urInput*/,
+ const osg::Vec2d& lrInput,
+ const osg::Vec2d& /*llInput*/,
+ ossimPlanetGrid::ModelPoints& outputGridPoints,
+ ossim_uint32 outputWidth,
+ ossim_uint32 outputHeight)const
+{
+ ossim_uint32 inputW = data->getWidth();
+ ossim_uint32 inputH = data->getHeight();
+ ossim_uint32 w = outputWidth;
+ ossim_uint32 h = outputHeight;
+ ossim_uint32 area = w*h;
+ ossim_uint32 idx = 0;
+ unsigned char* buf;
+ osg::Vec3d latLon;
+ unsigned char* b1 = NULL;
+ unsigned char* b2 = NULL;
+ unsigned char* b3 = NULL;
+ unsigned char np1 = 0;
+ unsigned char np2 = 0;
+ unsigned char np3 = 0;
+ bool bufExists = (image->data()!=0);
+
+ if(!bufExists)
+ {
+ buf = new unsigned char[area*4];
+ memset(buf, '\0', area*4);
+ }
+ else
+ {
+ buf = image->data();
+ }
+ unsigned char* bufPtr = buf;
+ if(data->getNumberOfBands()< 3)
+ {
+ b1 = (unsigned char*)data->getBuf(0);
+ b2 = (unsigned char*)data->getBuf(0);
+ b3 = (unsigned char*)data->getBuf(0);
+ np1 = (unsigned char)data->getNullPix(0);
+ np2 = (unsigned char)data->getNullPix(0);
+ np3 = (unsigned char)data->getNullPix(0);
+ }
+ else
+ {
+ b1 = (unsigned char*)data->getBuf(0);
+ b2 = (unsigned char*)data->getBuf(1);
+ b3 = (unsigned char*)data->getBuf(2);
+ np1 = (unsigned char)data->getNullPix(0);
+ np2 = (unsigned char)data->getNullPix(1);
+ np3 = (unsigned char)data->getNullPix(2);
+ }
+
+ ossim_uint32 y = 0;
+ ossim_uint32 x = 0;
+
+ osg::Vec2d inputT;
+ ossim_uint32 inputIdx = 0;
+ osg::Vec2d tempDelta;
+ double deltaInputX = std::fabs(lrInput[0] - ulInput[0]);
+ double deltaInputY = std::fabs(lrInput[1] - ulInput[1]);
+ if(!theTransparentColorFlag)
+ {
+ for(y = 0; y < h; ++y)
+ {
+ bufPtr = buf + y*w*4;
+
+ for(x = 0; x < w; ++x, bufPtr += 4)
+ {
+ latLon[0] = outputGridPoints[idx].y();
+ latLon[1] = outputGridPoints[idx].x();
+ tempDelta[0] = latLon[1] - ulInput[0];
+ tempDelta[1] = ulInput[1] - latLon[0];
+ tempDelta[0]/=deltaInputX;
+ tempDelta[1]/=deltaInputY;
+
+ ossim_float32 xf = tempDelta[0]*inputW;
+ ossim_float32 yf = tempDelta[1]*inputH;
+ ossim_int32 xi = (ossim_int32)(xf);
+ ossim_int32 yi = (ossim_int32)(yf);
+ if(xi == -1) xi++;
+ if(yi == -1) yi++;
+ if(xi == inputW) xi--;
+ if(yi == inputH) yi--;
+ if((xi>=0)&&
+ (xi<(int)inputW)&&
+ (yi>=0)&&
+ (yi<(int)inputH))
+ {
+ // if(xi < 0) xi =0;
+ // if(xi >= inputW) xi = inputW-1;
+ // if(yi < 0) yi = 0;
+ // if(yi >= inputH) yi = inputH-1;
+ inputIdx = yi*inputW + xi;
+ if((b1[inputIdx]==np1)&&
+ (b2[inputIdx]==np2)&&
+ (b3[inputIdx]==np3))
+ {
+ bufPtr[3] = 0;
+ bufPtr[0] = b1[inputIdx];
+ bufPtr[1] = b2[inputIdx];
+ bufPtr[2] = b3[inputIdx];
+ }
+ else
+ {
+
+ bufPtr[3] = 255;
+ ossim_int32 urx = xi+1;
+ ossim_int32 lry = yi+1;
+
+ if(urx >= (int)inputW) urx = inputW-1;
+ if(lry >= (int)inputH) lry = inputH-1;
+
+ double xt0 = xf - xi;
+ double yt0 = yf - yi;
+ double xt1 = 1-xt0;
+ double yt1 = 1-yt0;
+ double w00 = xt1*yt1;
+ double w01 = xt0*yt1;
+ double w10 = xt1*yt0;
+ double w11 = xt0*yt0;
+
+ int uridx = yi*inputW + urx;
+ int lridx = lry*inputW + urx;
+ int llidx = lry*inputW + xi;
+
+ ossim_float32 wsum = w00 + w01 + w10 + w11;
+ wsum = 1.0/wsum;
+ bufPtr[0] = (unsigned char)((b1[inputIdx]*w00 + b1[uridx]*w01 + b1[llidx]*w10+b1[lridx]*w11)*wsum);
+ bufPtr[1] = (unsigned char)((b2[inputIdx]*w00 + b2[uridx]*w01 + b2[llidx]*w10+b2[lridx]*w11)*wsum);
+ bufPtr[2] = (unsigned char)((b3[inputIdx]*w00 + b3[uridx]*w01 + b3[llidx]*w10+b3[lridx]*w11)*wsum);
+ // bufPtr[1] = b2[inputIdx];
+ // bufPtr[2] = b3[inputIdx];
+ bufPtr[3] = 255;
+
+ }
+ }
+ ++idx;
+ }
+ }
+ }
+ else
+ {
+ const unsigned char* transparentColor = &theTransparentColorVector.front();
+ for(y = 0; y < h; ++y)
+ {
+ bufPtr = buf + y*w*4;
+
+ for(x = 0; x < w; ++x, bufPtr += 4)
+ {
+ latLon[0] = outputGridPoints[idx].y();
+ latLon[1] = outputGridPoints[idx].x();
+ tempDelta[0] = latLon[1] - ulInput[0];
+ tempDelta[1] = ulInput[1] - latLon[0];
+ tempDelta[0]/=deltaInputX;
+ tempDelta[1]/=deltaInputY;
+
+ ossim_float32 xf = tempDelta[0]*inputW;
+ ossim_float32 yf = tempDelta[1]*inputH;
+ ossim_int32 xi = (ossim_int32)(xf);
+ ossim_int32 yi = (ossim_int32)(yf);
+ if(xi == -1) xi++;
+ if(yi == -1) yi++;
+ if(xi == inputW) xi--;
+ if(yi == inputH) yi--;
+ if((xi>=0)&&
+ (xi<(int)inputW)&&
+ (yi>=0)&&
+ (yi<(int)inputH))
+ {
+
+ // if(xi < 0) xi =0;
+ // if(xi >= inputW) xi = inputW-1;
+ // if(yi < 0) yi = 0;
+ // if(yi >= inputH) yi = inputH-1;
+ inputIdx = yi*inputW + xi;
+
+ if(((b1[inputIdx]==np1)&&
+ (b2[inputIdx]==np2)&&
+ (b3[inputIdx]==np3))||
+ ((b1[inputIdx]==transparentColor[0])&&
+ (b2[inputIdx]==transparentColor[1])&&
+ (b3[inputIdx]==transparentColor[2])))
+ {
+ bufPtr[3] = 0;
+ }
+ else
+ {
+ bufPtr[3] = 255;
+ ossim_int32 urx = xi+1;
+ ossim_int32 lry = yi+1;
+
+ if(urx >= (int)inputW) urx = inputW-1;
+ if(lry >= (int)inputH) lry = inputH-1;
+
+ double xt0 = xf - xi;
+ double yt0 = yf - yi;
+ double xt1 = 1-xt0;
+ double yt1 = 1-yt0;
+ double w00 = xt1*yt1;
+ double w01 = xt0*yt1;
+ double w10 = xt1*yt0;
+ double w11 = xt0*yt0;
+
+ int uridx = yi*inputW + urx;
+ int lridx = lry*inputW + urx;
+ int llidx = lry*inputW + xi;
+
+ ossim_float32 wsum = w00 + w01 + w10 + w11;
+ wsum = 1.0/wsum;
+ bufPtr[0] = (unsigned char)((b1[inputIdx]*w00 + b1[uridx]*w01 + b1[llidx]*w10+b1[lridx]*w11)*wsum);
+ bufPtr[1] = (unsigned char)((b2[inputIdx]*w00 + b2[uridx]*w01 + b2[llidx]*w10+b2[lridx]*w11)*wsum);
+ bufPtr[2] = (unsigned char)((b3[inputIdx]*w00 + b3[uridx]*w01 + b3[llidx]*w10+b3[lridx]*w11)*wsum);
+ // bufPtr[1] = b2[inputIdx];
+ // bufPtr[2] = b3[inputIdx];
+ bufPtr[3] = 255;
+ }
+ }
+ ++idx;
+ }
+ }
+ }
+ if(!bufExists)
+ {
+ image->setImage(w,
+ h,
+ 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ buf,
+ osg::Image::USE_NEW_DELETE);
+ }
+ image->setPixelStatus();
+}
+
+
+
+void ossimPlanetTextureLayer::convertToOsg(ossimImageData* data,
+ ossimPlanetImage* image,
+ const osg::Vec2d& ulInput,
+ const osg::Vec2d& /*urInput*/,
+ const osg::Vec2d& lrInput,
+ const osg::Vec2d& /*llInput*/,
+ std::vector<ossimPlanetGridUtility::GridPoint>& outputGridPoints,
+ const ossimPlanetGridUtility& utility,
+ ossim_uint32 outputWidth,
+ ossim_uint32 outputHeight)const
+{
+ ossim_uint32 inputW = data->getWidth();
+ ossim_uint32 inputH = data->getHeight();
+ ossim_uint32 w = outputWidth;
+ ossim_uint32 h = outputHeight;
+ ossim_uint32 area = w*h;
+ ossim_uint32 idx = 0;
+ unsigned char* buf;
+ osg::Vec3d latLon;
+ unsigned char* b1 = NULL;
+ unsigned char* b2 = NULL;
+ unsigned char* b3 = NULL;
+ unsigned char np1 = 0;
+ unsigned char np2 = 0;
+ unsigned char np3 = 0;
+ bool bufExists = (image->data()!=0);
+
+ if(!bufExists)
+ {
+ buf = new unsigned char[area*4];
+ memset(buf, '\0', area*4);
+ }
+ else
+ {
+ buf = image->data();
+ }
+ unsigned char* bufPtr = buf;
+ if(data->getNumberOfBands()< 3)
+ {
+ b1 = (unsigned char*)data->getBuf(0);
+ b2 = (unsigned char*)data->getBuf(0);
+ b3 = (unsigned char*)data->getBuf(0);
+ np1 = (unsigned char)data->getNullPix(0);
+ np2 = (unsigned char)data->getNullPix(0);
+ np3 = (unsigned char)data->getNullPix(0);
+ }
+ else
+ {
+ b1 = (unsigned char*)data->getBuf(0);
+ b2 = (unsigned char*)data->getBuf(1);
+ b3 = (unsigned char*)data->getBuf(2);
+ np1 = (unsigned char)data->getNullPix(0);
+ np2 = (unsigned char)data->getNullPix(1);
+ np3 = (unsigned char)data->getNullPix(2);
+ }
+
+ ossim_uint32 y = 0;
+ ossim_uint32 x = 0;
+
+ osg::Vec2d inputT;
+ ossim_uint32 inputIdx = 0;
+ osg::Vec2d tempDelta;
+ double deltaInputX = std::fabs(lrInput[0] - ulInput[0]);
+ double deltaInputY = std::fabs(lrInput[1] - ulInput[1]);
+ if(!theTransparentColorFlag)
+ {
+ for(y = 0; y < h; ++y)
+ {
+ bufPtr = buf + y*w*4;
+
+ for(x = 0; x < w; ++x, bufPtr += 4)
+ {
+ utility.getLatLon(latLon, outputGridPoints[idx]);
+ tempDelta[0] = latLon[ossimPlanetGridUtility::LON] - ulInput[0];
+ tempDelta[1] = ulInput[1] - latLon[ossimPlanetGridUtility::LAT];
+ tempDelta[0]/=deltaInputX;
+ tempDelta[1]/=deltaInputY;
+
+ ossim_float32 xf = tempDelta[0]*inputW;
+ ossim_float32 yf = tempDelta[1]*inputH;
+ ossim_int32 xi = (ossim_int32)(xf);
+ ossim_int32 yi = (ossim_int32)(yf);
+
+ if((xi>=0)&&
+ (xi<(int)inputW)&&
+ (yi>=0)&&
+ (yi<(int)inputH))
+ {
+// if(xi < 0) xi =0;
+// if(xi >= inputW) xi = inputW-1;
+// if(yi < 0) yi = 0;
+// if(yi >= inputH) yi = inputH-1;
+ inputIdx = yi*inputW + xi;
+ if((b1[inputIdx]==np1)&&
+ (b2[inputIdx]==np2)&&
+ (b3[inputIdx]==np3))
+ {
+ bufPtr[3] = 0;
+ bufPtr[0] = b1[inputIdx];
+ bufPtr[1] = b2[inputIdx];
+ bufPtr[2] = b3[inputIdx];
+ }
+ else
+ {
+
+ bufPtr[3] = 255;
+ ossim_int32 urx = xi+1;
+ ossim_int32 lry = yi+1;
+
+ if(urx >= (int)inputW) urx = inputW-1;
+ if(lry >= (int)inputH) lry = inputH-1;
+
+ double xt0 = xf - xi;
+ double yt0 = yf - yi;
+ double xt1 = 1-xt0;
+ double yt1 = 1-yt0;
+ double w00 = xt1*yt1;
+ double w01 = xt0*yt1;
+ double w10 = xt1*yt0;
+ double w11 = xt0*yt0;
+
+ int uridx = yi*inputW + urx;
+ int lridx = lry*inputW + urx;
+ int llidx = lry*inputW + xi;
+
+ ossim_float32 wsum = w00 + w01 + w10 + w11;
+ wsum = 1.0/wsum;
+ bufPtr[0] = (unsigned char)((b1[inputIdx]*w00 + b1[uridx]*w01 + b1[llidx]*w10+b1[lridx]*w11)*wsum);
+ bufPtr[1] = (unsigned char)((b2[inputIdx]*w00 + b2[uridx]*w01 + b2[llidx]*w10+b2[lridx]*w11)*wsum);
+ bufPtr[2] = (unsigned char)((b3[inputIdx]*w00 + b3[uridx]*w01 + b3[llidx]*w10+b3[lridx]*w11)*wsum);
+// bufPtr[1] = b2[inputIdx];
+// bufPtr[2] = b3[inputIdx];
+ bufPtr[3] = 255;
+
+ }
+ }
+ ++idx;
+ }
+ }
+ }
+ else
+ {
+ const unsigned char* transparentColor = &theTransparentColorVector.front();
+ for(y = 0; y < h; ++y)
+ {
+ bufPtr = buf + y*w*4;
+
+ for(x = 0; x < w; ++x, bufPtr += 4)
+ {
+ utility.getLatLon(latLon, outputGridPoints[idx]);
+ tempDelta[0] = latLon[ossimPlanetGridUtility::LON] - ulInput[0];
+ tempDelta[1] = ulInput[1] - latLon[ossimPlanetGridUtility::LAT];
+ //osg::Vec2d(latLon[1], latLon[0])-ulInput;
+// tempDelta[0] = tempDelta[0];
+// tempDelta[1] = tempDelta[1];
+ tempDelta[0]/=deltaInputX;
+ tempDelta[1]/=deltaInputY;
+
+ ossim_float32 xf = tempDelta[0]*inputW;
+ ossim_float32 yf = tempDelta[1]*inputH;
+ ossim_int32 xi = (ossim_int32)(xf);
+ ossim_int32 yi = (ossim_int32)(yf);
+ if((xi>=0)&&
+ (xi<(int)inputW)&&
+ (yi>=0)&&
+ (yi<(int)inputH))
+ {
+
+// if(xi < 0) xi =0;
+// if(xi >= inputW) xi = inputW-1;
+// if(yi < 0) yi = 0;
+// if(yi >= inputH) yi = inputH-1;
+ inputIdx = yi*inputW + xi;
+
+ if(((b1[inputIdx]==np1)&&
+ (b2[inputIdx]==np2)&&
+ (b3[inputIdx]==np3))||
+ ((b1[inputIdx]==transparentColor[0])&&
+ (b2[inputIdx]==transparentColor[1])&&
+ (b3[inputIdx]==transparentColor[2])))
+ {
+ bufPtr[3] = 0;
+ }
+ else
+ {
+ bufPtr[3] = 255;
+ ossim_int32 urx = xi+1;
+ ossim_int32 lry = yi+1;
+
+ if(urx >= (int)inputW) urx = inputW-1;
+ if(lry >= (int)inputH) lry = inputH-1;
+
+ double xt0 = xf - xi;
+ double yt0 = yf - yi;
+ double xt1 = 1-xt0;
+ double yt1 = 1-yt0;
+ double w00 = xt1*yt1;
+ double w01 = xt0*yt1;
+ double w10 = xt1*yt0;
+ double w11 = xt0*yt0;
+
+ int uridx = yi*inputW + urx;
+ int lridx = lry*inputW + urx;
+ int llidx = lry*inputW + xi;
+
+ ossim_float32 wsum = w00 + w01 + w10 + w11;
+ wsum = 1.0/wsum;
+ bufPtr[0] = (unsigned char)((b1[inputIdx]*w00 + b1[uridx]*w01 + b1[llidx]*w10+b1[lridx]*w11)*wsum);
+ bufPtr[1] = (unsigned char)((b2[inputIdx]*w00 + b2[uridx]*w01 + b2[llidx]*w10+b2[lridx]*w11)*wsum);
+ bufPtr[2] = (unsigned char)((b3[inputIdx]*w00 + b3[uridx]*w01 + b3[llidx]*w10+b3[lridx]*w11)*wsum);
+// bufPtr[1] = b2[inputIdx];
+// bufPtr[2] = b3[inputIdx];
+ bufPtr[3] = 255;
+ }
+ }
+ ++idx;
+ }
+ }
+ }
+ if(!bufExists)
+ {
+ image->setImage(w,
+ h,
+ 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ buf,
+ osg::Image::USE_NEW_DELETE);
+ }
+// image->flipVertical();
+ image->setPixelStatus();
+}
+
+OpenThreads::Mutex& ossimPlanetTextureLayer::mutex()
+{
+ return theMutex;
+}
+
+void ossimPlanetTextureLayer::getMetadata(ossimRefPtr<ossimXmlNode> /*metadata*/)const
+{
+ return;
+}
+
+ossimRefPtr<ossimXmlNode> ossimPlanetTextureLayer::saveXml(bool /*recurseFlag*/)const
+{
+ ossimXmlNode* node = new ossimXmlNode();
+ node->setTag(getClassName());
+ node->addChildNode("name", getName());
+ node->addChildNode("description", getDescription());
+ node->addChildNode("id", theId);
+ node->addChildNode("enableFlag", ossimString::toString(theEnableFlag));
+
+ ossimXmlNode* transparentColorNode = new ossimXmlNode;
+ transparentColorNode->setTag("transparentColor");
+ transparentColorNode->addChildNode("enableFlag", ossimString::toString(theTransparentColorFlag));
+ transparentColorNode->addChildNode("color", (ossimString::toString(theTransparentColorVector[0])+ " " +
+ ossimString::toString(theTransparentColorVector[1])+ " " +
+ ossimString::toString(theTransparentColorVector[2])));
+ node->addChildNode(transparentColorNode);
+ node->addChildNode("filterType", theFilterType);
+ if(theExtents.valid())
+ {
+ node->addChildNode(theExtents->saveXml().get());
+ }
+ if(theLookAt.valid())
+ {
+ node->addChildNode(theLookAt->saveXml().get());
+ }
+
+ return node;
+}
+
+bool ossimPlanetTextureLayer::loadXml(ossimRefPtr<ossimXmlNode> node)
+{
+ if(!node.valid()) return false;
+ const vector<ossimRefPtr<ossimXmlNode> >& childNodes = node->getChildNodes();
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = childNodes.size();
+ for(idx = 0; idx < upper; ++idx)
+ {
+ ossimString tag = childNodes[idx]->getTag();
+ if(tag == "name")
+ {
+ theName = childNodes[idx]->getText();
+ }
+ else if(tag == "description")
+ {
+ theDescription = childNodes[idx]->getText();
+ }
+ else if(tag == "id")
+ {
+ theId = childNodes[idx]->getText();
+ }
+ else if(tag == "enableFlag")
+ {
+ theEnableFlag = childNodes[idx]->getText().toBool();
+ }
+ else if(tag == "transparentColor")
+ {
+ ossimString temp;
+
+ if(childNodes[idx]->getChildTextValue(temp, "enableFlag"))
+ {
+ theTransparentColorFlag = temp.toBool();
+ }
+ if(childNodes[idx]->getChildTextValue(temp, "color"))
+ {
+ int r,g,b;
+ istringstream in(temp);
+ in>>r>>g>>b;
+ theTransparentColorVector[0] = (unsigned char)r;
+ theTransparentColorVector[1] = (unsigned char)g;
+ theTransparentColorVector[2] = (unsigned char)b;
+ }
+ }
+ else if(tag == "filterType")
+ {
+ theFilterType = childNodes[idx]->getText();
+ }
+ else if(tag == "ossimPlanetLookAt")
+ {
+ theLookAt = new ossimPlanetLookAt;
+ theLookAt->loadXml(childNodes[idx]);
+ }
+ }
+
+ return true;
+}
+
+ossimPlanetTextureLayer* ossimPlanetTextureLayer::findLayerByName(const ossimString& layerName,
+ bool /*recurseFlag*/)
+{
+ if(layerName == name())
+ {
+ return this;
+ }
+
+ return 0;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetTextureLayer::findLayerByName(const ossimString& layerName,
+ bool /*recurseFlag*/)const
+{
+ if(layerName == name())
+ {
+ return this;
+ }
+
+ return 0;
+}
+
+ossimPlanetTextureLayer* ossimPlanetTextureLayer::findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& id)
+{
+ if((name() == layerName)&&
+ (this->id() == id))
+ {
+ return this;
+ }
+
+ return 0;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetTextureLayer::findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& id)const
+{
+ if((name() == layerName)&&
+ (this->id() == id))
+ {
+ return this;
+ }
+
+ return 0;
+}
+
+ossimPlanetTextureLayer* ossimPlanetTextureLayer::findLayerById(const ossimString& id,
+ bool /*recurseFlag*/)
+{
+ if(this->id() == id) return this;
+ return 0;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetTextureLayer::findLayerById(const ossimString& id,
+ bool /*recurseFlag*/)const
+{
+ if(this->id() == id) return this;
+ return 0;
+}
+
+void ossimPlanetTextureLayer::remove()
+{
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theParentList.size(); ++idx)
+ {
+ ossimPlanetTextureLayerGroup* p = parent(idx);
+ p->removeLayer(this);
+ }
+}
+
+ossim_float32 ossimPlanetTextureLayer::brightness()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theBrightness;
+}
+
+ossim_float32 ossimPlanetTextureLayer::contrast()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theContrast;
+}
+
+ossim_float32 ossimPlanetTextureLayer::opacity()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theOpacity;
+}
+
+/**
+ * Allows one to enable brightness contrast settings.
+ */
+void ossimPlanetTextureLayer::setBrightnessContrast(ossim_float32 brightnessValue,
+ ossim_float32 contrastValue,
+ bool notifyFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theBrightness = brightnessValue;
+ theContrast = contrastValue;
+ if(notifyFlag)
+ {
+ notifyRefreshExtent(getExtents().get());
+ }
+}
+
+void ossimPlanetTextureLayer::setBrightness(ossim_float32 brightnessValue,
+ bool notifyFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theBrightness = brightnessValue;
+ if(notifyFlag)
+ {
+ notifyRefreshExtent(getExtents().get());
+ }
+}
+
+void ossimPlanetTextureLayer::setContrast(ossim_float32 contrastValue,
+ bool notifyFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theContrast = contrastValue;
+ if(notifyFlag)
+ {
+ notifyRefreshExtent(getExtents().get());
+ }
+}
+
+/**
+ * Allows one to set the opacity.
+ *
+ * @param opacityValue value of 1.0 is fully opaque and a value of 0 is fully transparent
+ */
+void ossimPlanetTextureLayer::setOpacity(ossim_float32 opacityValue,
+ bool notifyFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theOpacity = opacityValue;
+
+ if(notifyFlag)
+ {
+ notifyRefreshExtent(getExtents().get());
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayerGroup.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayerGroup.cpp
new file mode 100644
index 0000000..3128632
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayerGroup.cpp
@@ -0,0 +1,1086 @@
+#include <ossimPlanet/ossimPlanetTextureLayerGroup.h>
+#include <algorithm>
+#include <stack>
+#include <queue>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimGpt.h>
+
+
+class ossimPlanetTextureLayerListener : public ossimPlanetTextureLayerCallback
+{
+public:
+ ossimPlanetTextureLayerListener(ossimPlanetTextureLayer* layer)
+ :theLayer(layer)
+ {
+ }
+
+ void setLayer(ossimPlanetTextureLayer* layer)
+ {
+ theLayer = layer;
+ }
+ virtual void layerAdded(osg::ref_ptr<ossimPlanetTextureLayer> layer)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyLayerAdded(layer);
+ }
+ }
+ virtual void refreshExtent(osg::ref_ptr<ossimPlanetExtents> extent)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyRefreshExtent(extent);
+ }
+ }
+ virtual void layerRemoved(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ osg::ref_ptr<ossimPlanetTextureLayer> parent)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyLayerRemoved(layer, parent);
+ }
+ }
+ virtual void propertyChanged(const ossimString& name,
+ const ossimPlanetTextureLayer* object)
+ {
+ if(theLayer)
+ {
+ theLayer->notifyPropertyChanged(name, object);
+ }
+ }
+protected:
+ ossimPlanetTextureLayer* theLayer;
+};
+
+ossimPlanetTextureLayerGroup::ossimPlanetTextureLayerGroup()
+:theBackgroundColor(1.0,1.0,1.0,1.0),
+theFillEmptyNullTileMaxLevel(-1),
+theFillTranslucentPixelsWithBackgroundEnabled(false)
+{
+ theName = "ossimPlanetTextureLayerGroup";
+ theDescription = "ossimPlanetTextureLayerGroup";
+ theChildListener = new ossimPlanetTextureLayerListener(this);
+}
+
+ossimPlanetTextureLayerGroup::ossimPlanetTextureLayerGroup(const ossimPlanetTextureLayerGroup& src)
+ :ossimPlanetTextureLayer(src)
+{
+
+ theChildListener = new ossimPlanetTextureLayerListener(this);
+ if(&src != this)
+ {
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < src.theChildrenList.size(); ++idx)
+ {
+ if(src.theChildrenList[idx].valid())
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = src.theChildrenList[idx]->dup();
+ addBottom(layer.get());
+ }
+ else
+ {
+ // empty for now. Not sure if we want to push a null layer
+ }
+ }
+ }
+
+ theBackgroundColor = src.theBackgroundColor;
+ theFillEmptyNullTileMaxLevel = src.theFillEmptyNullTileMaxLevel;
+
+ theFillTranslucentPixelsWithBackgroundEnabled = src.theFillTranslucentPixelsWithBackgroundEnabled;
+}
+
+ossimPlanetTextureLayerGroup::~ossimPlanetTextureLayerGroup()
+{
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theChildrenList.size();++idx)
+ {
+ theChildrenList[idx]->removeCallback(theChildListener);
+ theChildrenList[idx]->removeParent(this);
+ }
+}
+
+ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::dup()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ return new ossimPlanetTextureLayerGroup(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::dupType()const
+{
+ return new ossimPlanetTextureLayerGroup();
+}
+
+ossimString ossimPlanetTextureLayerGroup::getClassName()const
+{
+ return "ossimPlanetTextureLayerGroup";
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetTextureLayerGroup::updateExtents()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ theStateCode = ossimPlanetTextureLayer_VALID;
+ ossim_uint32 idx;
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ theStateCode = (ossimPlanetTextureLayerStateCode)(theStateCode|theChildrenList[idx]->updateExtents());
+
+ const osg::ref_ptr<ossimPlanetExtents> extents = theChildrenList[idx]->getExtents();
+
+ if(idx != 0)
+ {
+ theExtents->combine(extents.get());
+ }
+ else
+ {
+ theExtents = extents->clone();
+ }
+
+ }
+ theDirtyExtentsFlag = false;
+
+ return theStateCode;
+}
+
+void ossimPlanetTextureLayerGroup::updateStats()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(theChildrenListMutex);
+ theStats->setTotalTextureSize(0);
+ theStats->setBytesTransferred(0);
+ ossim_uint32 idx;
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ theChildrenList[idx]->updateStats();
+ osg::ref_ptr<ossimPlanetTextureLayer::Stats> stats = theChildrenList[idx]->getStats();
+ theStats->setBytesTransferred(theStats->bytesTransferred() + stats->bytesTransferred());
+ theStats->setTotalTextureSize(theStats->totalTextureSize() + stats->totalTextureSize());
+ }
+ theDirtyStatsFlag = false;
+}
+
+void ossimPlanetTextureLayerGroup::resetStats()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(theChildrenListMutex);
+ ossim_uint32 idx;
+ theStats->setBytesTransferred(0);
+ theStats->setTotalTextureSize(0);
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ osg::ref_ptr<ossimPlanetTextureLayer::Stats> stats = theChildrenList[idx]->getStats();
+ theStats->setTotalTextureSize(theStats->totalTextureSize() + stats->totalTextureSize());
+ }
+}
+
+bool ossimPlanetTextureLayerGroup::hasTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ if(!theEnableFlag)
+ {
+ return false;
+ }
+ if(tileId.level() == 0) return true;
+
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+
+ if(theExtents.valid())
+ {
+ osg::ref_ptr<ossimPlanetExtents> extents = new ossimPlanetExtents;
+ if(grid.convertToGeographicExtents(tileId, *extents, width, height))
+ {
+ if(!theExtents->intersectsLatLon(*extents)&&
+ !theExtents->intersectsScale(*extents))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ bool result = false;
+ ossim_uint32 idx = 0;
+ for(idx = 0; ((idx < theChildrenList.size())&&!result); ++idx)
+ {
+ if(theChildrenList[idx]->hasTexture(width, height, tileId, grid))
+ {
+ result = true;
+ }
+ }
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetTextureLayerGroup::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 padding)
+{
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ osg::ref_ptr<ossimPlanetExtents> tileExtents = new ossimPlanetExtents;
+ if(grid.convertToGeographicExtents(tileId, *tileExtents, width, height))
+ {
+ if(theExtents.valid())
+ {
+ if(!theExtents->intersectsLatLon(*tileExtents)&&
+ !theExtents->intersectsScale(*tileExtents))
+ {
+ return 0;
+ }
+ }
+ }
+ ossim_uint32 idx = 0;
+ osg::ref_ptr<ossimPlanetImage> result;
+ ossim_float32 opacity = 1.0;
+ if(theChildrenList.size() == 1)
+ {
+ result = theChildrenList[idx]->getTexture(width, height, tileId, grid);
+ }
+ else
+ {
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ if(theChildrenList[idx].valid()&&(theChildrenList[idx]->opacity() > 0.0))
+ {
+ osg::ref_ptr<ossimPlanetImage> image = theChildrenList[idx]->getTexture(width, height, tileId, grid);
+
+ if(image.valid())
+ {
+
+ ossimPlanetImage::ossimPlanetImagePixelStatus pixelStatus = image->getPixelStatus();
+ if(result.valid())
+ {
+ // use previous opacity for merging
+ //mergeImage(image.get(), result.get(), 1.0 - opacity);
+ mergeImage(image.get(), result.get(), opacity);
+ // update opacity
+ opacity = theChildrenList[idx]->opacity();
+ result = image;
+ result->getPixelStatus();
+ pixelStatus = result->getPixelStatus();
+ if((pixelStatus == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)&&
+ (opacity == 1.0))
+ {
+ // we are finished
+ break;
+ }
+ }
+ else
+ {
+ opacity = theChildrenList[idx]->opacity();
+ if((opacity == 1.0) &&
+ (pixelStatus == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL))
+ {
+ result = image;
+ break;
+ }
+ else
+ {
+ result = (ossimPlanetImage*)image->clone(osg::CopyOp::DEEP_COPY_ALL);
+ }
+ }// end if result.valid()
+ }// end if image.valid()
+ }
+ }
+ }
+ if(result.get())
+ {
+ result = applyBrightnessContrast(result.get(), true);
+ }
+ if((!result.valid()&&((ossim_int32)tileId.level()<=theFillEmptyNullTileMaxLevel))||
+ (result.valid()&&result->getPixelStatus()==ossimPlanetImage::ossimPlanetImagePixelStatus_EMPTY))
+ {
+ ossim_uint32 area = width*height;
+ unsigned char* newData = new unsigned char[area*4];
+ ossim_uint8 r = static_cast<ossim_uint8>(theBackgroundColor[0]*255);
+ ossim_uint8 g = static_cast<ossim_uint8>(theBackgroundColor[1]*255);
+ ossim_uint8 b = static_cast<ossim_uint8>(theBackgroundColor[2]*255);
+ ossim_uint8 a = static_cast<ossim_uint8>(theBackgroundColor[3]*255);
+ if(r==g&&r==b&&r==a)
+ {
+ memset(newData, r, area*4);
+ }
+ else
+ {
+ ossim_uint32 idx = 0;
+ unsigned char* newDataPtr = newData;
+ for(idx = 0; idx < area; ++idx,newDataPtr+=4)
+ {
+ newDataPtr[0] = r;
+ newDataPtr[1] = g;
+ newDataPtr[2] = b;
+ newDataPtr[3] = a;
+ }
+ }
+ result = new ossimPlanetImage();
+ result->setImage(width, height, 1,
+ GL_RGBA,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ newData,
+ osg::Image::USE_NEW_DELETE);
+ }
+ else if(result.valid()&&theFillTranslucentPixelsWithBackgroundEnabled)
+ {
+ ossimPlanetImage::ossimPlanetImagePixelStatus pixelStatus = result->getPixelStatus();
+ if(pixelStatus != ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ unsigned char* dataPtr = result->data();
+ ossim_uint32 area = result->width()*result->height();
+ ossim_uint32 idx = 0;
+ ossim_uint8 r = static_cast<ossim_uint8>(theBackgroundColor[0]*255);
+ ossim_uint8 g = static_cast<ossim_uint8>(theBackgroundColor[1]*255);
+ ossim_uint8 b = static_cast<ossim_uint8>(theBackgroundColor[2]*255);
+ ossim_uint8 a = static_cast<ossim_uint8>(theBackgroundColor[3]*255);
+ for(idx = 0; idx < area;++idx,dataPtr+=4)
+ {
+ if(dataPtr[3] < 1)
+ {
+ dataPtr[0] = r;
+ dataPtr[1] = g;
+ dataPtr[2] = b;
+ dataPtr[3] = a;
+ }
+ }
+ result->setPixelStatus();
+ }
+
+ }
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetTextureLayerGroup::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ if(!theEnableFlag)
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ ossim_uint32 idx = 0;
+ osg::ref_ptr<ossimPlanetImage> result;
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+// unsigned int w = utility.getTileWidth();
+ unsigned int h = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row,
+ col );
+ if(!theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ return 0;
+ }
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/h;
+// double deltaLon = deltaX/w;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ if(gsd.y>theExtents->getMaxScale())//!theExtents->intersectsScale(gsd.y,
+ // gsd.y))
+ {
+ return 0;
+ }
+
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ if(theChildrenList[idx].valid())
+ {
+ const osg::ref_ptr<ossimPlanetExtents> extents = theChildrenList[idx]->getExtents();
+
+ if(extents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ osg::ref_ptr<ossimPlanetImage> image = theChildrenList[idx]->getTexture(level, row, col, utility);
+ if(image.valid())
+ {
+ if(result.valid())
+ {
+ mergeImage(image.get(), result.get());
+ result = image;
+ result->setPixelStatus();
+ if(result->getPixelStatus() == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ return result;
+ }
+ }
+ else
+ {
+ result = (ossimPlanetImage*)image->clone(osg::CopyOp::DEEP_COPY_ALL);
+ if(result->getPixelStatus() == ossimPlanetImage::ossimPlanetImagePixelStatus_FULL)
+ {
+ return result;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+ossimPlanetTextureLayerGroup* ossimPlanetTextureLayerGroup::asGroup()
+{
+ return this;
+}
+
+const ossimPlanetTextureLayerGroup* ossimPlanetTextureLayerGroup::asGroup()const
+{
+ return this;
+}
+
+bool ossimPlanetTextureLayerGroup::swapLayers(osg::ref_ptr<ossimPlanetTextureLayer> layer1,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer2,
+ bool notifyFlag)
+{
+ ossim_int32 idx1 = findLayerIndex(layer1.get());
+ ossim_int32 idx2 = findLayerIndex(layer2.get());
+
+ if(idx1 < 0 || idx2 < 0) return false;
+
+ return swapLayers(idx1, idx2, notifyFlag);
+}
+
+bool ossimPlanetTextureLayerGroup::swapLayers(ossim_uint32 idx1, ossim_uint32 idx2, bool notifyFlag)
+{
+ if((idx1 < theChildrenList.size())&&
+ (idx2 < theChildrenList.size()))
+ {
+ std::swap(theChildrenList[idx1], theChildrenList[idx2]);
+ if(notifyFlag)
+ {
+ if(theChildrenList[idx1]->getExtents().valid()&&
+ theChildrenList[idx2]->getExtents().valid())
+ {
+ osg::ref_ptr<ossimPlanetExtents> extent = new ossimPlanetExtents(*theChildrenList[idx1]->getExtents());
+ extent->combine(theChildrenList[idx2]->getExtents().get());
+ notifyRefreshExtent(extent);
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool ossimPlanetTextureLayerGroup::replaceLayer(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ bool result = false;
+ if(layer.valid()&&idx < theChildrenList.size())
+ {
+ if(!containsLayerNoMutex(layer))
+ {
+ if(theChildrenList[idx].valid())
+ {
+ theChildrenList[idx]->removeCallback(theChildListener);
+ theChildrenList[idx]->removeParent(this);
+ }
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenList[idx] = layer.get();
+ dirtyExtents();
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ }
+
+ return result;
+}
+
+bool ossimPlanetTextureLayerGroup::addTop(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag)
+{
+ if(layer.get() == this) return false;
+// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ bool result = false;
+
+ if(layer.valid())
+ {
+ if(!containsLayer(layer))
+ {
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenListMutex.lock();
+ theChildrenList.insert(theChildrenList.begin(), layer);
+ theChildrenListMutex.unlock();
+ dirtyExtents(); // notify parent layers
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ }
+
+ return result;
+}
+
+bool ossimPlanetTextureLayerGroup::addBeforeIdx(ossim_uint32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag)
+{
+ bool result = false;
+
+ theChildrenListMutex.lock();
+ if((idx < theChildrenList.size())&&(!containsLayerNoMutex(layer)))
+ {
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenList.insert(theChildrenList.begin()+idx, layer);
+ theChildrenListMutex.unlock();
+ dirtyExtents();
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ else
+ {
+ theChildrenListMutex.unlock();
+ }
+
+ return result;
+}
+
+bool ossimPlanetTextureLayerGroup::addBeforeLayer(const osg::ref_ptr<ossimPlanetTextureLayer> beforeLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd,
+ bool notifyFlag)
+{
+ return addBeforeIdx(findLayerIndex(beforeLayer),
+ layerToAdd,
+ notifyFlag);
+}
+
+bool ossimPlanetTextureLayerGroup::addAfterIdx(ossim_int32 idx,
+ osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag)
+{
+ bool result = false;
+
+ theChildrenListMutex.lock();
+ if(containsLayerNoMutex(layer))
+ {
+ return result;
+ }
+ if(idx == -1)
+ {
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenList.insert(theChildrenList.begin(), layer);
+ theChildrenListMutex.unlock();
+ dirtyExtents();
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ else if(idx < theChildrenList.size())
+ {
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenList.insert(theChildrenList.begin()+idx+1, layer);
+ theChildrenListMutex.unlock();
+ dirtyExtents();
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ else if(idx == theChildrenList.size())
+ {
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenList.push_back(layer.get());
+ theChildrenListMutex.unlock();
+ dirtyExtents();
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ else
+ {
+ theChildrenListMutex.unlock();
+ }
+ return result;
+}
+
+bool ossimPlanetTextureLayerGroup::addAfterLayer(const osg::ref_ptr<ossimPlanetTextureLayer> afterLayer,
+ osg::ref_ptr<ossimPlanetTextureLayer> layerToAdd,
+ bool notifyFlag)
+{
+ return addAfterIdx(findLayerIndex(afterLayer),
+ layerToAdd,
+ notifyFlag);
+}
+
+bool ossimPlanetTextureLayerGroup::addBottom(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag)
+{
+ bool result = false;
+ if(layer.valid())
+ {
+ if(!containsLayerNoMutex(layer))
+ {
+ layer->addParent(this);
+ layer->addCallback(theChildListener);
+ theChildrenListMutex.lock();
+ theChildrenList.push_back(layer);
+ theChildrenListMutex.unlock();
+ dirtyExtents();
+ dirtyStats();
+ result = true;
+ if(notifyFlag)
+ {
+ notifyLayerAdded(layer);
+ }
+ }
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetTextureLayerGroup::removeLayer(ossim_uint32 idx,
+ bool notifyFlag)
+{
+ theChildrenListMutex.lock();
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = removeLayerNoMutex(idx, false);
+ theChildrenListMutex.unlock();
+ if(notifyFlag)
+ {
+ notifyLayerRemoved(layer, this);
+ }
+ return layer.get();
+}
+
+void ossimPlanetTextureLayerGroup::removeLayers(ossim_uint32 idx, ossim_uint32 length,
+ bool notifyFlag)
+{
+ std::vector<osg::ref_ptr<ossimPlanetTextureLayer> > layerList;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ layerList = removeLayersNoMutex(idx, length, false);
+ }
+ if(notifyFlag)
+ {
+ ossim_uint32 tempIdx = layerList.size();
+ for(tempIdx = 0; tempIdx < layerList.size();++tempIdx)
+ {
+ notifyLayerRemoved(layerList[tempIdx].get(), this);
+ }
+ }
+
+}
+
+bool ossimPlanetTextureLayerGroup::removeLayer(osg::ref_ptr<ossimPlanetTextureLayer> layer,
+ bool notifyFlag)
+{
+ theChildrenListMutex.lock();
+ bool result = removeLayerNoMutex(layer, false);
+ theChildrenListMutex.unlock();
+ if(notifyFlag)
+ {
+ notifyLayerRemoved(layer, this);
+ }
+ return result;
+}
+
+
+ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::findLayerByName(const ossimString& layerName,
+ bool recurseFlag)
+{
+ std::queue<ossimPlanetTextureLayer*> tempQueue;
+
+ if(name() == layerName) return this;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; (idx < theChildrenList.size());++idx)
+ {
+ if(theChildrenList[idx]->name() == layerName) return theChildrenList[idx].get();
+ if(theChildrenList[idx]->asGroup()&&recurseFlag)
+ {
+ tempQueue.push(theChildrenList[idx].get());
+ }
+ }
+ ossimPlanetTextureLayer* result = 0;
+
+ while(!tempQueue.empty()&&!result)
+ {
+ result = tempQueue.front()->findLayerByName(layerName, recurseFlag);
+ tempQueue.pop();
+ }
+
+ return result;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::findLayerByName(const ossimString& layerName,
+ bool recurseFlag)const
+{
+ std::queue<const ossimPlanetTextureLayer*> tempQueue;
+
+ if(theName == layerName) return this;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; (idx < theChildrenList.size());++idx)
+ {
+ if(theChildrenList[idx]->name() == layerName) return theChildrenList[idx].get();
+ if(theChildrenList[idx]->asGroup()&&recurseFlag)
+ {
+ tempQueue.push(theChildrenList[idx].get());
+ }
+ }
+ const ossimPlanetTextureLayer* result = 0;
+
+ while(!tempQueue.empty()&&!result)
+ {
+ result = tempQueue.front()->findLayerByName(layerName, recurseFlag);
+ tempQueue.pop();
+ }
+
+ return result;
+}
+ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& id)
+{
+ ossimPlanetTextureLayer* layer = this;
+ if(layer->name() != layerName)
+ {
+ layer = findLayerByName(layerName, true);
+ }
+ if(layer)
+ {
+ return layer->findLayerById(id, true);
+ }
+
+ return 0;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::findLayerByNameAndId(const ossimString& layerName,
+ const ossimString& id)const
+{
+ const ossimPlanetTextureLayer* layer = this;
+ if(layer->name() != layerName)
+ {
+ layer = findLayerByName(layerName, true);
+ }
+ if(layer)
+ {
+ return layer->findLayerById(id, true);
+ }
+ return 0;
+}
+ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::findLayerById(const ossimString& layerId,
+ bool recurseFlag)
+{
+ std::queue<ossimPlanetTextureLayer*> tempQueue;
+
+ if(theId == layerId) return this;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; (idx < theChildrenList.size());++idx)
+ {
+ if(theChildrenList[idx]->id() == layerId) return theChildrenList[idx].get();
+ if(theChildrenList[idx]->asGroup()&&recurseFlag)
+ {
+ tempQueue.push(theChildrenList[idx].get());
+ }
+ }
+ ossimPlanetTextureLayer* result = 0;
+
+ while(!tempQueue.empty()&&!result)
+ {
+ result = tempQueue.front()->findLayerById(layerId, recurseFlag);
+ tempQueue.pop();
+ }
+
+ return result;
+}
+
+const ossimPlanetTextureLayer* ossimPlanetTextureLayerGroup::findLayerById(const ossimString& layerId,
+ bool recurseFlag)const
+{
+ std::queue<const ossimPlanetTextureLayer*> tempQueue;
+
+ if(theId == layerId) return this;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ ossim_uint32 idx = 0;
+ for(idx = 0; (idx < theChildrenList.size());++idx)
+ {
+ if(theChildrenList[idx]->id() == layerId) return theChildrenList[idx].get();
+ if(theChildrenList[idx]->asGroup()&&recurseFlag)
+ {
+ tempQueue.push(theChildrenList[idx].get());
+ }
+ }
+ const ossimPlanetTextureLayer* result = 0;
+
+ while(!tempQueue.empty()&&!result)
+ {
+ result = tempQueue.front()->findLayerById(layerId, recurseFlag);
+ tempQueue.pop();
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetTextureLayerGroup::removeLayerNoMutex(ossim_uint32 idx, bool notifyFlag)
+{
+ osg::ref_ptr<ossimPlanetTextureLayer> result;
+ if(idx < theChildrenList.size())
+ {
+ result = theChildrenList[idx];
+ result->removeParent(this);
+ result->removeCallback(theChildListener);
+ theChildrenList.erase(theChildrenList.begin()+idx);
+ dirtyExtents();
+ dirtyStats();
+ }
+ if(notifyFlag)
+ {
+ notifyLayerRemoved(result, this);
+ }
+ return result;
+}
+
+std::vector<osg::ref_ptr<ossimPlanetTextureLayer> > ossimPlanetTextureLayerGroup::removeLayersNoMutex(ossim_uint32 idx, ossim_uint32 length, bool notifyFlag)
+{
+ std::vector<osg::ref_ptr<ossimPlanetTextureLayer> > layerList;
+ if(idx >= theChildrenList.size()) return layerList;
+ ossim_uint32 endIdx = idx;
+ ossim_uint32 maxCount = ossim::min(idx+length, (ossim_uint32)theChildrenList.size());
+ for(endIdx = idx; endIdx <maxCount ; ++endIdx)
+ {
+ theChildrenList[endIdx]->removeParent(this);
+ theChildrenList[endIdx]->removeCallback(theChildListener);
+ layerList.push_back(theChildrenList[endIdx]);
+ }
+ theChildrenList.erase(theChildrenList.begin() + idx,
+ theChildrenList.begin() + maxCount);
+ dirtyExtents();
+ dirtyStats();
+ ossim_uint32 tempIdx = 0;
+
+ return layerList;
+}
+
+bool ossimPlanetTextureLayerGroup::removeLayerNoMutex(osg::ref_ptr<ossimPlanetTextureLayer> layer, bool notifyFlag)
+{
+
+ ossim_int32 idx = findLayerIndexNoMutex(layer);
+ if(idx > -1)
+ {
+ return removeLayerNoMutex((ossim_uint32)idx, notifyFlag).valid();
+ }
+
+ return false;
+}
+
+ossim_int32 ossimPlanetTextureLayerGroup::findLayerIndexNoMutex(osg::ref_ptr<ossimPlanetTextureLayer> layer)const
+{
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ if(theChildrenList[idx].get() == layer.get())
+ {
+ return (ossim_int32)idx;
+ }
+ }
+
+ return -1;
+
+}
+
+ossim_int32 ossimPlanetTextureLayerGroup::findLayerIndex(osg::ref_ptr<ossimPlanetTextureLayer> layer)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ return findLayerIndexNoMutex(layer);
+}
+
+bool ossimPlanetTextureLayerGroup::containsLayer(osg::ref_ptr<ossimPlanetTextureLayer> layer)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ return containsLayerNoMutex(layer);
+}
+
+ossim_uint32 ossimPlanetTextureLayerGroup::numberOfLayers()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ return theChildrenList.size();
+}
+
+const osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetTextureLayerGroup::layer(ossim_uint32 idx)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ if(idx < theChildrenList.size())
+ {
+ return theChildrenList[idx];
+ }
+
+ return 0;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetTextureLayerGroup::layer(ossim_uint32 idx)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+ if(idx < theChildrenList.size())
+ {
+ return theChildrenList[idx];
+ }
+
+ return 0;
+}
+
+static bool gsdCmp( osg::ref_ptr<ossimPlanetTextureLayer> a, osg::ref_ptr<ossimPlanetTextureLayer> b )
+{
+ osg::ref_ptr<ossimPlanetExtents> aExtents = a->getExtents();
+ osg::ref_ptr<ossimPlanetExtents> bExtents = b->getExtents();
+
+ double aScale = aExtents->getMinScale();
+ double bScale = bExtents->getMinScale();
+
+ if(aScale > 0.0)
+ {
+ if(bScale > 0.0)
+ {
+ return aScale < bScale;
+ }
+ }
+ else if(bScale > 0.0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+void ossimPlanetTextureLayerGroup::setFillNullOrEmptyTileMaxLevel(ossim_int32 maxLevel)
+{
+ theFillEmptyNullTileMaxLevel = maxLevel;
+}
+
+void ossimPlanetTextureLayerGroup::setBackgroundColor(const osg::Vec4f& color)
+{
+ theBackgroundColor = color;
+}
+
+void ossimPlanetTextureLayerGroup::setFillTranslucentPixelsWithBackground(bool on)
+{
+ theFillTranslucentPixelsWithBackgroundEnabled = on;
+}
+
+void ossimPlanetTextureLayerGroup::sortByGsd()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theChildrenListMutex);
+
+ std::sort(theChildrenList.begin(),
+ theChildrenList.end(),
+ gsdCmp);
+}
+
+bool ossimPlanetTextureLayerGroup::containsLayerNoMutex(osg::ref_ptr<ossimPlanetTextureLayer> layer)const
+{
+ std::stack<const ossimPlanetTextureLayerGroup* >tempStack;
+// ossim_uint32 idx = 0;
+ tempStack.push(this);
+
+ while(!tempStack.empty())
+ {
+ const ossimPlanetTextureLayerGroup* current = tempStack.top();
+ tempStack.pop();
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < current->theChildrenList.size(); ++idx)
+ {
+ if(current->theChildrenList[idx].get() == layer.get())
+ {
+ return true;
+ }
+ if(current->theChildrenList[idx].valid())
+ {
+ if(current->theChildrenList[idx]->asGroup())
+ {
+ tempStack.push(current->theChildrenList[idx]->asGroup());
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+ossimRefPtr<ossimXmlNode> ossimPlanetTextureLayerGroup::saveXml(bool recurseFlag)const
+{
+ ossimRefPtr<ossimXmlNode> result = ossimPlanetTextureLayer::saveXml(recurseFlag);
+
+ if(recurseFlag)
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theChildrenList.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> node = theChildrenList[idx]->saveXml().get();
+ result->addChildNode(node.get());
+ }
+ }
+
+ return result;
+}
+
+bool ossimPlanetTextureLayerGroup::loadXml(ossimRefPtr<ossimXmlNode> node)
+{
+ std::cout << "ossimPlanetTextureLayerGroup::loadXml: NOT IMPLEMENTED YET!!!" << std::endl;
+ return ossimPlanetTextureLayer::loadXml(node);
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayerRegistry.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayerRegistry.cpp
new file mode 100644
index 0000000..09f3ec3
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTextureLayerRegistry.cpp
@@ -0,0 +1,105 @@
+#include <algorithm>
+
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <ossimPlanet/ossimPlanetStandardTextureLayerFactory.h>
+#include <OpenThreads/ScopedLock>
+#include <iostream>
+
+ossimPlanetTextureLayerRegistry* ossimPlanetTextureLayerRegistry::theInstance = 0;
+
+ossimPlanetTextureLayerRegistry::ossimPlanetTextureLayerRegistry()
+{
+ theInstance = this;
+ destroyingFlag = true;
+}
+
+ossimPlanetTextureLayerRegistry::~ossimPlanetTextureLayerRegistry()
+{
+ destroyingFlag = true;
+
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theFactoryList.size(); ++idx)
+ {
+ delete theFactoryList[idx];
+ theFactoryList[idx] = 0;
+ }
+
+ theInstance = 0;
+
+}
+
+ossimPlanetTextureLayerRegistry* ossimPlanetTextureLayerRegistry::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetTextureLayerRegistry;
+ theInstance->registerFactory(ossimPlanetStandardTextureLayerFactory::instance());
+ }
+
+ return theInstance;
+}
+
+void ossimPlanetTextureLayerRegistry::registerFactory(ossimPlanetTextureLayerFactory* factory)
+{
+ theFactoryListMutex.writeLock();
+ if(!containsFactory(factory))
+ {
+ theFactoryList.push_back(factory);
+ }
+ theFactoryListMutex.writeUnlock();
+}
+
+void ossimPlanetTextureLayerRegistry::registerFactoryToFront(ossimPlanetTextureLayerFactory* factory)
+{
+ theFactoryListMutex.writeLock();
+ if(!containsFactory(factory))
+ {
+ theFactoryList.insert(theFactoryList.begin(), factory);
+ }
+ theFactoryListMutex.writeUnlock();
+}
+
+void ossimPlanetTextureLayerRegistry::unregisterFactory(ossimPlanetTextureLayerFactory* factory)
+{
+ if(destroyingFlag) return;
+ theFactoryListMutex.writeLock();
+
+ std::vector<ossimPlanetTextureLayerFactory*>::iterator iter = std::find(theFactoryList.begin(),
+ theFactoryList.end(),
+ factory);
+
+ if(iter != theFactoryList.end())
+ {
+ theFactoryList.erase(iter);
+ }
+ theFactoryListMutex.writeUnlock();
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetTextureLayerRegistry::createLayer(const ossimString& name, bool openAllEntriesFlag)const
+{
+ ossim_uint32 idx=0;
+ osg::ref_ptr<ossimPlanetTextureLayer> result;
+ theFactoryListMutex.readLock();
+ for(idx = 0; ((idx < theFactoryList.size())&&(!result.valid()));++idx)
+ {
+ result = theFactoryList[idx]->createLayer(name, openAllEntriesFlag);
+ }
+ theFactoryListMutex.readUnlock();
+ return result;
+}
+
+bool ossimPlanetTextureLayerRegistry::containsFactory(ossimPlanetTextureLayerFactory* factory)const
+{
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < theFactoryList.size(); ++idx)
+ {
+ if(theFactoryList[idx] == factory)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetThread.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetThread.cpp
new file mode 100644
index 0000000..7ce9520
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetThread.cpp
@@ -0,0 +1,77 @@
+#include <ossimPlanet/ossimPlanetThread.h>
+#include <ossimPlanet/ossimPlanetThreadPool.h>
+
+ossimPlanetThread::ossimPlanetThread()
+{
+ theImplementation = 0;
+ theThreadPool = 0;
+ theRetainThreadFlag = false;
+}
+
+void ossimPlanetThread::run()
+{
+ if(theImplementation)
+ {
+ theImplementation->run();
+ if(theThreadPool&&!theRetainThreadFlag)
+ {
+ theThreadPool->makeAvailable(this);
+ }
+ }
+}
+
+int ossimPlanetThread::cancel()
+{
+ if(theImplementation)
+ {
+ theImplementation->cancel();
+ while(isRunning())
+ {
+ OpenThreads::Thread::YieldCurrentThread();
+ }
+ }
+
+ return 0;
+}
+
+void ossimPlanetThread::updateThreadBlock()
+{
+ if(theImplementation)
+ {
+ theImplementation->updateThreadBlock();
+ }
+}
+
+void ossimPlanetThread::setImplementation(ossimPlanetThreadImp* implementation)
+{
+ if(theImplementation)
+ {
+ theImplementation->setThread(0);
+ theImplementation->cancel();
+ }
+ theImplementation = implementation;
+ if(theImplementation)
+ {
+ theImplementation->setThread(this);
+ }
+}
+
+void ossimPlanetThread::setThreadPool(ossimPlanetThreadPool* threadPool)
+{
+ theThreadPool = threadPool;
+}
+
+ossimPlanetThreadImp* ossimPlanetThread::implementation()
+{
+ return theImplementation;
+}
+
+const ossimPlanetThreadImp* ossimPlanetThread::implementation()const
+{
+ return theImplementation;
+}
+
+void ossimPlanetThread::setRetainThreadFlag(bool flag)
+{
+ theRetainThreadFlag = flag;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetThreadImp.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetThreadImp.cpp
new file mode 100644
index 0000000..27deb20
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetThreadImp.cpp
@@ -0,0 +1,33 @@
+#include <ossimPlanet/ossimPlanetThreadImp.h>
+#include <ossimPlanet/ossimPlanetThread.h>
+ossimPlanetThreadImp::~ossimPlanetThreadImp()
+{
+
+}
+
+int ossimPlanetThreadImp::cancel()
+{
+ setDoneFlag(true);
+ updateThreadBlock();
+ return 0;
+}
+
+void ossimPlanetThreadImp::setDoneFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theImpMutex);
+ theDoneFlag = flag;
+}
+
+bool ossimPlanetThreadImp::doneFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theImpMutex);
+ return theDoneFlag;
+}
+
+void ossimPlanetThreadImp::threadPooled()
+{
+}
+
+void ossimPlanetThreadImp::updateThreadBlock()
+{
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetThreadPool.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetThreadPool.cpp
new file mode 100644
index 0000000..1ec4d3c
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetThreadPool.cpp
@@ -0,0 +1,84 @@
+#include <ossimPlanet/ossimPlanetThreadPool.h>
+#include <ossimPlanet/ossimPlanetThread.h>
+#include <algorithm>
+#include <iostream>
+#include <OpenThreads/ScopedLock>
+unsigned int ossimPlanetThreadPool::theMaxThreads = 32;
+
+osg::ref_ptr<ossimPlanetThreadPool> ossimPlanetThreadPool::theInstance = 0;
+osg::ref_ptr<ossimPlanetThreadPool> ossimPlanetThreadPool::instance()
+{
+ if(!theInstance)
+ {
+ theInstance = new ossimPlanetThreadPool;
+ }
+ return theInstance;
+}
+
+ossimPlanetThreadPool::ossimPlanetThreadPool()
+{
+ theInstance = this;
+}
+
+unsigned int ossimPlanetThreadPool::totalThreads()const
+{
+ return theAvailableList.size()+theUnavailableList.size();
+}
+
+
+void ossimPlanetThreadPool::makeAvailable(osg::ref_ptr<ossimPlanetThread> thread)
+{
+ ossimPlanetThreadImp* imp = thread->implementation();
+ bool pooled = false;
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theListMutex);
+ std::vector<osg::ref_ptr<ossimPlanetThread> >::iterator iter = std::find(theUnavailableList.begin(),
+ theUnavailableList.end(),
+ thread);
+ if(iter!=theUnavailableList.end())
+ {
+ pooled = true;
+ theUnavailableList.erase(iter);
+ thread->setImplementation(0);
+ theAvailableList.push_back(thread);
+ }
+ }
+ if(pooled)
+ {
+ imp->threadPooled();
+ }
+
+
+}
+
+osg::ref_ptr<ossimPlanetThread> ossimPlanetThreadPool::nextAvailable()
+{
+ osg::ref_ptr<ossimPlanetThread> thread = NULL;
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theListMutex);
+ if(theAvailableList.size() < 1)
+ {
+ if(totalThreads() < theMaxThreads)
+ {
+ osg::ref_ptr<ossimPlanetThread> thread = new ossimPlanetThread;
+ thread->setThreadPool(this);
+ theAvailableList.push_back(thread);
+ }
+ else
+ {
+ return thread;
+ }
+ }
+ if(theAvailableList.size() > 0)
+ {
+ thread = theAvailableList[theAvailableList.size()-1];
+ theAvailableList.pop_back();
+ theUnavailableList.push_back(thread);
+ }
+
+ return thread;
+}
+
+void ossimPlanetThreadPool::setMaxThread(int maxThreads)
+{
+ theMaxThreads = maxThreads;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetTileRequest.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetTileRequest.cpp
new file mode 100644
index 0000000..4abe45a
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetTileRequest.cpp
@@ -0,0 +1,864 @@
+#include <ossimPlanet/ossimPlanetTileRequest.h>
+#include <ossimPlanet/ossimPlanetTerrainTile.h>
+#include <ossimPlanet/ossimPlanetTerrainLayer.h>
+#include <ossimPlanet/ossimPlanetTerrain.h>
+#include <ossimPlanet/ossimPlanetCubeGrid.h>
+#include <osgUtil/GLObjectsVisitor>
+#include <osg/Timer>
+
+#if (((OPENSCENEGRAPH_MAJOR_VERSION<2) || (OPENSCENEGRAPH_MAJOR_VERSION==2 && (OPENSCENEGRAPH_MINOR_VERSION<8 || (OPENSCENEGRAPH_MINOR_VERSION==8 && OPENSCENEGRAPH_PATCH_VERSION<=2)))))
+# define USE_OLD_VBO_COMPILE 0
+#else
+# define USE_OLD_VBO_COMPILE 1
+#endif
+void ossimPlanetTileRequest::FindCompileableGLObjectsVisitor::apply(osg::Node& node)
+{
+ apply(node.getStateSet());
+
+ traverse(node);
+}
+
+void ossimPlanetTileRequest::FindCompileableGLObjectsVisitor::apply(osg::Geode& geode)
+{
+ apply(geode.getStateSet());
+
+ for(unsigned int i=0;i<geode.getNumDrawables();++i)
+ {
+ apply(geode.getDrawable(i));
+ }
+
+ traverse(geode);
+}
+
+void ossimPlanetTileRequest::FindCompileableGLObjectsVisitor::apply(osg::StateSet* stateset)
+{
+ if (stateset)
+ {
+ bool compileStateSet = false;
+ for(unsigned int i=0;i<stateset->getTextureAttributeList().size();++i)
+ {
+ osg::Texture* texture = dynamic_cast<osg::Texture*>(stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
+ // Has this texture already been encountered?
+ if (texture && !theTextureSet.count(texture))
+ {
+ // if (texture->getTextureParameterDirty(theContextId)||
+ // (texture->getTextureObject(theContextId)==0))
+ {
+ theDataToCompile.textures.insert(texture);
+ }
+ }
+ }
+ }
+}
+
+void ossimPlanetTileRequest::FindCompileableGLObjectsVisitor::apply(osg::Drawable* drawable)
+{
+ if (theDrawableSet.count(drawable))
+ return;
+
+ apply(drawable->getStateSet());
+
+ if(drawable->getUseVertexBufferObjects())
+ {
+ const osg::Geometry* geometry = drawable->asGeometry();
+ if(geometry)
+ {
+ osg::Geometry::ArrayList arrayList;
+ geometry->getArrayList(arrayList);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < arrayList.size();++idx)
+ {
+ if(arrayList[idx]->getVertexBufferObject())
+ {
+// if(arrayList[idx]->getVertexBufferObject()->isDirty(theContextId))
+ {
+// theDataToCompile.vbos.insert(arrayList[idx]->getVertexBufferObject());
+ }
+ }
+ }
+ }
+ }
+}
+
+ossimPlanetTileRequest::ossimPlanetTileRequest(ossimPlanetTerrainTile* tile)
+{
+ setThreadSafeRefUnref(true);
+ setTile(tile);
+}
+
+void ossimPlanetTileRequest::setTile(ossimPlanetTerrainTile* tile)
+{
+ theTile = tile;
+ if(theTile.valid())
+ {
+ theTileId = theTile->tileId();
+ theTerrain = theTile->terrain();
+ }
+}
+ossimPlanetTerrainTile* ossimPlanetTileRequest::tile()
+{
+ return theTile.get();
+}
+
+const ossimPlanetTerrainTile* ossimPlanetTileRequest::tile()const
+{
+ return theTile.get();
+}
+
+bool ossimPlanetTileRequest::compileObjects(osg::RenderInfo& renderInfo,
+ double availableTimeInSeconds)
+{
+ return true; // we have finished
+}
+
+bool ossimPlanetTileRequest::populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet)
+{
+ return true;
+}
+
+ossimPlanetTileRequestQueue::ossimPlanetTileRequestQueue(bool sortFlag)
+:theCurrentFrameNumber(0),
+theSortFlag(sortFlag)
+{
+
+}
+
+void ossimPlanetTileRequestQueue::sort()
+{
+ if(theSortFlag)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ theOperationQueue.sort(ossimPlanetTileRequest::SortFunctor());
+ }
+}
+
+osg::ref_ptr<ossimPlanetOperation> ossimPlanetTileRequestQueue::nextOperation(bool blockIfEmptyFlag)
+{
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ ossimPlanetOperation::List::iterator iter = theOperationQueue.begin();
+ ossimPlanetOperation::List::iterator endIter = theOperationQueue.end();
+
+ while(iter != endIter)
+ {
+ // std::cout << "CHECKING STOPPED!!!!!!!!!!!!!!!!"<< std::endl;
+ ossimPlanetTileRequest* tileRequest = dynamic_cast<ossimPlanetTileRequest*>((*iter).get());
+ if(!tileRequest->isRequestCurrent(theCurrentFrameNumber)||tileRequest->isStopped())
+ {
+ iter = theOperationQueue.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+ if(theSortFlag)
+ {
+ sort();
+ }
+ osg::ref_ptr<ossimPlanetOperation> operation = ossimPlanetOperationQueue::nextOperation(blockIfEmptyFlag).get();
+ while(operation.valid())
+ {
+ ossimPlanetTileRequest* tileRequest = dynamic_cast<ossimPlanetTileRequest*>(operation.get());
+ if(!tileRequest)
+ {
+ return operation;
+ }
+ if(tileRequest->isRequestCurrent(theCurrentFrameNumber)&&!tileRequest->isStopped())
+ {
+ return operation;
+ }
+ operation = 0;
+ operation = ossimPlanetOperationQueue::nextOperation(blockIfEmptyFlag).get();
+ }
+
+ return 0;
+}
+
+void ossimPlanetTileRequestQueue::add(ossimPlanetTileRequest* request)
+{
+ if(request)
+ {
+ if(request->referenceCount() == 1)
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theOperationQueueMutex);
+ request->setState(ossimPlanetOperation::READY_STATE);
+ theOperationQueue.push_back(request);
+ }
+ }
+}
+
+void ossimPlanetTileRequestThreadQueue::add(ossimPlanetTileRequest* request)
+
+{
+ if(request)
+ {
+ if(request->referenceCount() == 1)
+ {
+ ossimPlanetOperationThreadQueue::add(request);
+ }
+ }
+}
+void ossimPlanetTileRequestThreadQueue::run()
+{
+ bool firstTime = true;
+
+ do
+ {
+ // osg::notify(osg::NOTICE)<<"In thread loop "<<this<<std::endl;
+ osg::ref_ptr<ossimPlanetOperation> operation;
+ osg::ref_ptr<ossimPlanetOperationQueue> queue;
+
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ queue = theOperationQueue;
+ }
+ operation = queue->nextOperation(true);
+
+ if (theDoneFlag) break;
+
+ if (operation.valid())
+ {
+ ossimPlanetTileRequest* request = dynamic_cast<ossimPlanetTileRequest*>(operation.get());
+ if(request&&request->isRequestCurrent(theCurrentFrameNumber))
+ {
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ theCurrentOperation = operation;
+ }
+
+ if(operation->state() == ossimPlanetOperation::READY_STATE)
+ {
+ operation->start();
+ if(operation->state() != ossimPlanetOperation::CANCELED_STATE)
+ {
+ ossimPlanetTileRequest* tileRequest = dynamic_cast<ossimPlanetTileRequest*>(operation.get());
+ if(tileRequest)
+ {
+ osg::ref_ptr<ossimPlanetTerrainTile> tile = tileRequest->tile();
+ if(tile.valid())
+ {
+ if(tileRequest->needsToCompile())
+ {
+
+ tile->terrain()->addRequestToNeedToCompileQueue(tileRequest);
+ }
+ else
+ {
+ tile->terrain()->addRequestToReadyToApplyQueue(tileRequest);
+ }
+ }
+ }
+ }
+ }
+ {
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theThreadMutex);
+ theCurrentOperation = 0;
+ }
+ }
+ operation = 0;
+ }
+
+ if (firstTime)
+ {
+ // do a yield to get round a peculiar thread hang when testCancel() is called
+ // in certain cirumstances - of which there is no particular pattern.
+ YieldCurrentThread();
+ firstTime = false;
+ }
+ } while (!testCancel() && !theDoneFlag);
+}
+
+#if 0
+void ossimPlanetTerrain::TileRequestThreadQueue::applyToGraph(double availableTime)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theFinishedOperationsListMutex);
+ osg::Timer_t startTick = osg::Timer::instance()->tick();
+ bool doneFlag = theFinishedOperationsList.empty();
+ ossim_uint32 operationCount = 0;
+ while(!doneFlag)
+ {
+ theFinishedOperationsList.sort(SortRequestFunctor());
+ (*theFinishedOperationsList.begin())->applyToGraph();
+ theFinishedOperationsList.erase(theFinishedOperationsList.begin());
+ ++operationCount;
+ double delta = osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick());
+ doneFlag = (theFinishedOperationsList.empty()||
+ (delta > availableTime)||
+ (operationCount >=theMaxNumberOfOperationsToApply));
+ }
+}
+#endif
+
+ossimPlanetSplitRequest::ossimPlanetSplitRequest(ossimPlanetTerrainTile* tile)
+:ossimPlanetTileRequest(tile)
+{
+ if(tile)
+ {
+ tile->vacantChildIds(theNeededChildrenList);
+ }
+
+}
+
+
+void ossimPlanetSplitRequest::run()
+{
+ theNewTiles.clear();
+ if((theNeededChildrenList.size()>0)&&(state()!=CANCELED_STATE)&&(theTile.valid()))
+ {
+ ossim_uint32 idx = 0;
+ osg::ref_ptr<ossimPlanetTerrainImageLayer> elevationLayer = theTile->elevationLayer();
+ if(!elevationLayer)
+ {
+ return;
+ }
+ ossim_uint32 textureWidth = theTile->terrain()->textureTileWidth();
+ ossim_uint32 textureHeight = theTile->terrain()->textureTileHeight();
+ ossim_uint32 elevationWidth = theTile->terrain()->elevationTileWidth();
+ ossim_uint32 elevationHeight = theTile->terrain()->elevationTileHeight();
+ osg::ref_ptr<ossimPlanetImage> inputElevationImage = elevationLayer->image();
+ osg::ref_ptr<ossimPlanetImage> scaledImage;
+ // elevationImage = new ossimPlanetImage(inputElevationImage->tileId());
+ // elevationImage->allocateImage(inputElevationImage->widthWithoutPadding(),
+ // inputElevationImage->heightWithoutPadding(),
+ // 1,
+ // inputElevationImage->getPixelFormat(),
+ // inputElevationImage->getDataType(),
+ // inputElevationImage->getPacking());
+ // elevationImage->setPadding(0);
+
+ if(inputElevationImage.valid())
+ {
+ if(inputElevationImage->padding() > 0)
+ {
+ // strip padding for scaling
+ //
+ osg::ref_ptr<ossimPlanetImage> tempImage = new ossimPlanetImage(*inputElevationImage);
+ tempImage->stripPadding();
+ inputElevationImage = tempImage;
+ }
+
+ scaledImage = inputElevationImage->scaleImagePowerOf2();
+ }
+ if(theNeededChildrenList.size() > 0)
+ {
+ ossimPlanetTerrainTile* newTile = new ossimPlanetTerrainTile(theNeededChildrenList[idx]);
+ newTile->setTerrain(theTerrain.get());
+ ossim_uint32 idx2 = 0;
+ for(idx2 = 0; idx2 < newTile->numberOfImageLayers(); ++idx2)
+ {
+ if(theTile->imageLayer(idx2) && newTile->imageLayer(idx2))
+ {
+#if 1
+ bool hasDataFlag = newTile->terrain()->textureLayer(idx2)->hasTexture(textureWidth,
+ textureHeight,
+ newTile->tileId(),
+ *theTile->grid());
+ newTile->imageLayer(idx2)->setNoMoreDataFlag(!hasDataFlag);//theTile->imageLayer(idx2)->noMoreDataFlag());
+#else
+ newTile->imageLayer(idx2)->setNoMoreDataFlag(theTile->imageLayer(idx2)->noMoreDataFlag());
+#endif
+
+ }
+ }
+ osg::ref_ptr<ossimPlanetImage> elevationImage;
+ osg::ref_ptr<ossimPlanetImageCache> cache = theTile->terrain()->elevationCache();
+ if(cache.valid())
+ {
+ elevationImage = cache->get(newTile->tileId());
+ }
+ // interpolate elevation if it's present
+ //
+ if(!elevationImage.valid())
+ {
+ if(inputElevationImage.valid())
+ {
+ bool hasDataFlag = newTile->terrain()->elevationLayer()->hasTexture(elevationWidth,
+ elevationHeight,
+ newTile->tileId(),
+ *theTile->grid());
+// ossim_uint32 xLength = inputElevationImage->s()>>1;
+// ossim_uint32 yLength = inputElevationImage->t()>>1;
+ ossim_uint32 x;
+ ossim_uint32 y;
+ theTile->terrainTechnique()->childTreePosition(theNeededChildrenList[idx], x, y);
+
+#if 1
+ x=x*(scaledImage->getWidth()*.5) - x*scaledImage->padding();
+ y=y*(scaledImage->getHeight()*.5) - y*scaledImage->padding();
+// elevationImage = new ossimPlanetImage(inputElevationImage->tileId());
+// elevationImage->allocateImage(inputElevationImage->widthWithoutPadding(),
+// inputElevationImage->heightWithoutPadding(),
+// 1,
+// inputElevationImage->getPixelFormat(),
+// inputElevationImage->getDataType(),
+// inputElevationImage->getPacking());
+// elevationImage->setPadding(0);
+ elevationImage = new ossimPlanetImage(*inputElevationImage.get());
+ scaledImage->copyTo(x, y, elevationImage.get());
+#else
+ elevationImage = new ossimPlanetImage(*inputElevationImage.get());
+ x=x*(elevationImage->getWidth()*.5) - x*elevationImage->padding();
+ y=y*(elevationImage->getHeight()*.5) - y*elevationImage->padding();
+ elevationImage->copySubImageAndInsertPointsPowerOf2(x,
+ y,
+ elevationImage->getWidth(),
+ elevationImage->getHeight(),
+ inputElevationImage.get());
+#endif
+// std::cout << "scaled w, h = " << scaledImage->getWidth() << ", " << scaledImage->getHeight() << std::endl;
+// std::cout << "w, h = " << inputElevationImage->getWidth() << ", " << inputElevationImage->getHeight() << std::endl;
+// std::cout << "x, y = " << x << ", " << y << std::endl;
+
+ newTile->elevationLayer()->setImage(elevationImage.get());
+ }
+ // newTile->elevationLayer()->setNoMoreDataFlag(!hasDataFlag);//theTile->elevationLayer()->noMoreDataFlag());
+ newTile->elevationLayer()->setNoMoreDataFlag(theTile->elevationLayer()->noMoreDataFlag());
+ }
+ else
+ {
+ newTile->elevationLayer()->setImage(elevationImage.get());
+ newTile->elevationLayer()->setNoMoreDataFlag(theTile->elevationLayer()->noMoreDataFlag());
+ }
+ newTile->init();
+ theNewTiles.push_back(newTile);
+ }
+ }
+}
+
+bool ossimPlanetSplitRequest::populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet)
+{
+ if((state()!=CANCELED_STATE)&&theNewTiles.size()&&theTile.valid())
+ {
+ if(theDataToCompile.textures.empty()&&
+ theDataToCompile.vbos.empty())
+ {
+ FindCompileableGLObjectsVisitor visitor(theDataToCompile,
+ theTerrain.get(),
+ 0);
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theNewTiles.size() ; ++idx)
+ {
+ theNewTiles[idx]->accept(visitor);
+ }
+ }
+ if(!theDataToCompile.textures.empty())
+ {
+ for(osgUtil::IncrementalCompileOperation::ContextSet::iterator itr = contexts.begin();
+ itr != contexts.end();
+ ++itr)
+ {
+ ++compileSet._numberCompileListsToCompile;
+
+ osgUtil::IncrementalCompileOperation::CompileList& cl = compileSet._compileMap[*itr];
+
+ for(TextureSetList::iterator iter = theDataToCompile.textures.begin();
+ iter!=theDataToCompile.textures.end();++iter)
+ {
+ cl.add((*iter).get());
+ }
+ }
+ }
+ }
+ return true;
+}
+bool ossimPlanetSplitRequest::compileObjects(osg::RenderInfo& renderInfo,
+ double availableTimeInSeconds)
+{
+ // osg::Timer_t tick = osg::Timer::instance()->tick();
+ if((state()!=CANCELED_STATE)&&theNewTiles.size()&&theTile.valid()&&renderInfo.getState())
+ {
+ if(theDataToCompile.textures.empty()&&
+ theDataToCompile.vbos.empty())
+ {
+ FindCompileableGLObjectsVisitor visitor(theDataToCompile,
+ theTerrain.get(),
+ renderInfo.getState()->getContextID());
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theNewTiles.size() ; ++idx)
+ {
+ theNewTiles[idx]->accept(visitor);
+ }
+ }
+ // do textures first
+ while(!theDataToCompile.textures.empty())
+ {
+ (*theDataToCompile.textures.begin())->compileGLObjects(*renderInfo.getState());
+ theDataToCompile.textures.erase(theDataToCompile.textures.begin());
+ }
+ while(!theDataToCompile.vbos.empty())
+ {
+#if 0
+#if USE_OLD_VBO_COMPILE
+ (*theDataToCompile.vbos.begin())->compileBuffer(*renderInfo.getState());
+#else
+ osg::GLBufferObject* glBufferObj = (*theDataToCompile.vbos.begin())->getOrCreateGLBufferObject(renderInfo.getState()->getContextID());
+
+ if(glBufferObj&&glBufferObj->isDirty())
+ {
+ glBufferObj->compileBuffer();
+ }
+#endif
+#endif
+ theDataToCompile.vbos.erase(theDataToCompile.vbos.begin());
+
+ }
+ }
+ if(state()==CANCELED_STATE)
+ {
+ theNewTiles.clear();
+ }
+
+ return true;
+// if(osg::Timer::instance()->delta_m(tick, osg::Timer::instance()->tick()) > 1.0)
+// {
+// std::cout << "ossimPlanetTextureRequest::compile: TOO LONG!!!!" << std::endl;
+// }
+}
+
+
+void ossimPlanetSplitRequest::applyToGraph()
+{
+ if((state()!=CANCELED_STATE)&&
+ theTile.valid()&&theNewTiles.size())//&&(theTile->state() == ossimPlanetTerrainTile::NEED_SPLITTING))
+ {
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < theNewTiles.size();++idx)
+ {
+ theTile->addChild(theNewTiles[idx].get());
+ }
+ }
+ theNewTiles.clear();
+}
+
+void ossimPlanetSplitRequest::setTile(ossimPlanetTerrainTile* tile)
+{
+ ossimPlanetTileRequest::setTile(tile);
+ theNeededChildrenList.clear();
+ if(tile)
+ {
+ tile->vacantChildIds(theNeededChildrenList);
+ }
+}
+
+ossimPlanetTextureRequest::ossimPlanetTextureRequest()
+:ossimPlanetTileRequest(){
+}
+
+ossimPlanetTextureRequest::ossimPlanetTextureRequest(ossimPlanetTerrainTile* tile,
+ ossim_uint32 imageLayerIdx)
+:ossimPlanetTileRequest(tile)
+{
+ setImageLayerIdx(imageLayerIdx);
+}
+
+void ossimPlanetTextureRequest::setTextureLayerIndices(const std::vector<ossim_uint32>& values)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ ossim_uint32 idx;
+ theResultList.clear();
+ for(idx = 0; idx < values.size();++idx)
+ {
+ theResultList.insert(std::make_pair(values[idx], Result()));
+ }
+}
+
+void ossimPlanetTextureRequest::run()
+{
+ if(theTile.valid()&&theTerrain.valid())
+ {
+ if(state() != CANCELED_STATE)
+ {
+ ossim_uint32 w,h;
+ w = theTile->terrain()->textureTileWidth();
+ h = theTile->terrain()->textureTileHeight();
+
+ const ossimPlanetTerrainTileId& tileId = theTile->tileId();
+ TextureResultMap::iterator iter = theResultList.begin();
+ while(iter!=theResultList.end())
+ {
+ osg::ref_ptr<ossimPlanetTerrainImageLayer> imageLayer = theTile->imageLayer(iter->first);
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = theTerrain->textureLayer(iter->first);
+ if(layer.valid())
+ {
+ iter->second.theImage = layer->getTexture(w,
+ h,
+ tileId,
+ *theTile->grid());
+ if(iter->second.theImage.valid())
+ {
+ iter->second.theImage->setId(tileId);
+ iter->second.theTexture = theTile->terrainTechnique()->newImageLayerTexture(iter->first);
+ iter->second.theTexture->setImage(iter->second.theImage.get());
+ }
+ }
+ ++iter;
+ }
+ }
+ }
+}
+
+
+bool ossimPlanetTextureRequest::compileObjects(osg::RenderInfo& renderInfo,
+ double availableTimeInSeconds)
+{
+ osg::Timer_t tick = osg::Timer::instance()->tick();
+ TextureResultMap::iterator iter = theResultList.begin();
+ while(iter!=theResultList.end())
+ {
+ if((state()!=CANCELED_STATE)&&
+ iter->second.theTexture.get()&&
+ theTile.valid()&&renderInfo.getState())
+ {
+ if ((iter->second.theTexture->getTextureParameterDirty(renderInfo.getState()->getContextID()))||
+ (iter->second.theTexture->getTextureObject(renderInfo.getState()->getContextID())==0))
+ {
+ iter->second.theTexture->compileGLObjects(*renderInfo.getState());
+ }
+ }
+ //double delta = osg::Timer::instance()->delta_s(tick, osg::Timer::instance()->tick());
+ ++iter;
+ }
+
+ return true; // no more compilation required
+}
+
+bool ossimPlanetTextureRequest::populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet)
+{
+ if((state()!=CANCELED_STATE))
+ {
+ if(!theResultList.empty())
+ {
+ for(osgUtil::IncrementalCompileOperation::ContextSet::iterator itr = contexts.begin();
+ itr != contexts.end();
+ ++itr)
+ {
+ ++compileSet._numberCompileListsToCompile;
+
+ osgUtil::IncrementalCompileOperation::CompileList& cl = compileSet._compileMap[*itr];
+ TextureResultMap::iterator iter = theResultList.begin();
+ while(iter!=theResultList.end())
+ {
+ cl.add(iter->second.theTexture.get());
+ ++iter;
+ }
+ }
+
+ }
+ }
+ return true;
+}
+
+
+void ossimPlanetTextureRequest::applyToGraph()
+{
+ //std::cout << " ossimPlanetTerrain::TextureRequest::applyToGraph() entered...." << std::endl;
+ if(state()!=CANCELED_STATE)
+ {
+ TextureResultMap::iterator iter = theResultList.begin();
+ while(iter!=theResultList.end()&&theTile.valid())
+ {
+
+ if(iter->second.theTexture.valid())
+ {
+ theTile->terrainTechnique()->setImageLayerTexture(iter->second.theTexture.get(), iter->first);
+ }
+ else
+ {
+ if(theTile->imageLayer(iter->first))
+ {
+ theTile->imageLayer(iter->first)->setNoMoreDataFlag(true);
+ }
+ }
+ ++iter;
+ }
+ }
+}
+
+ossimPlanetElevationRequest::ossimPlanetElevationRequest()
+:ossimPlanetTileRequest()
+{
+}
+
+ossimPlanetElevationRequest::ossimPlanetElevationRequest(ossimPlanetTerrainTile* tile,
+ ossim_uint32 width,
+ ossim_uint32 height)
+:ossimPlanetTileRequest(tile)
+{
+}
+
+void ossimPlanetElevationRequest::run()
+{
+ theNewMesh = 0;
+ theImage = 0;
+ theDataToCompile.textures.clear();
+ theDataToCompile.vbos.clear();
+ ossim_int32 padding = 1;
+ if(theTile.valid()&&theTile->grid()&&theTile->terrain())
+ {
+ if(state() != CANCELED_STATE)
+ {
+ ossim_uint32 w, h;
+ w = theTile->terrain()->elevationTileWidth();
+ h = theTile->terrain()->elevationTileHeight();
+ osg::ref_ptr<ossimPlanetTerrainImageLayer> imageLayer = theTile->elevationLayer();
+ osg::ref_ptr<ossimPlanetTextureLayer> elevLayer = theTile->terrain()->elevationLayer();
+ if(imageLayer.valid()&&elevLayer.valid())
+ {
+ osg::ref_ptr<ossimPlanetImageCache> cache = theTile->terrain()->elevationCache();
+ if(cache.valid())
+ {
+ theImage = cache->get(theTile->tileId());
+ }
+// if(elevLayer->hasTexture(w,
+// h,
+// theTile->tileId(),
+// *theTile->grid()) || (theTile->tileId().level()==0))
+ {
+ const ossimPlanetTerrainTileId& tileId = theTile->tileId();
+ if(!theImage)
+ {
+ theImage = elevLayer->getTexture(w,
+ h,
+ theTile->tileId(),
+ *theTile->grid(),
+ padding);
+ if(cache.valid())
+ {
+ cache->addOrUpdate(theImage.get());
+ }
+ }
+ if(theImage.valid())
+ {
+ theImage->setId(tileId);
+
+ theNewMesh = new ossimPlanetTerrainTile(theTile->tileId());
+ theNewMesh->copyCommonParameters(theTile.get());
+ //imageLayer->setImage(theImage.get());
+ //imageLayer->setRefreshFlag(false);
+ theNewMesh->elevationLayer()->setImage(theImage.get());
+ theNewMesh->init();
+ }
+ else
+ {
+ //std::cout << "NO ELEVATION" << std::endl;
+ }
+ }
+#if 0
+ else
+ {
+ if(theTile->parentTile())
+ {
+ osg::ref_ptr<ossimPlanetImage> img = theTile->parentTile()->elevationLayer()->image();
+ if(img.valid())
+ {
+ // we will do it the way the split does it
+ //
+ std::cout << "WE CAN SPLIT!!!!" << std::endl;
+ }
+ else
+ {
+ std::cout << "WE CAN'T SPLIT!!!!" << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "NO PARENT WE CAN'T SPLIT!!!!" << std::endl;
+ }
+ }
+#endif
+ }
+ }
+ }
+}
+
+bool ossimPlanetElevationRequest::compileObjects(osg::RenderInfo& renderInfo,
+ double availableTimeInSeconds)
+{
+ if(!renderInfo.getState()||!theNewMesh.valid()) return true; // no more to compile
+ if(theDataToCompile.textures.empty()&&
+ theDataToCompile.vbos.empty())
+ {
+ FindCompileableGLObjectsVisitor visitor(theDataToCompile,
+ theTerrain.get(),
+ renderInfo.getState()->getContextID());
+ theNewMesh->accept(visitor);
+ }
+ // do textures first
+ while(!theDataToCompile.textures.empty())
+ {
+ (*theDataToCompile.textures.begin())->compileGLObjects(*renderInfo.getState());
+ theDataToCompile.textures.erase(theDataToCompile.textures.begin());
+ }
+ while(!theDataToCompile.vbos.empty())
+ {
+#if 0
+#if USE_OLD_VBO_COMPILE
+ (*theDataToCompile.vbos.begin())->compileBuffer(*renderInfo.getState());
+#else
+ osg::GLBufferObject* glBufferObj = (*theDataToCompile.vbos.begin())->getOrCreateGLBufferObject(renderInfo.getState()->getContextID());
+ if(glBufferObj&&glBufferObj->isDirty())
+ {
+ glBufferObj->compileBuffer();
+ }
+#endif
+#endif
+ theDataToCompile.vbos.erase(theDataToCompile.vbos.begin());
+ }
+// osg::Timer_t tick = osg::Timer::instance()->tick();
+ if(state()==CANCELED_STATE)
+ {
+ theNewMesh = 0;
+ }
+ return true; // no more to compile
+}
+bool ossimPlanetElevationRequest::populateCompileSet(osgUtil::IncrementalCompileOperation::ContextSet& contexts,
+ osgUtil::IncrementalCompileOperation::CompileSet& compileSet)
+{
+ if((state()!=CANCELED_STATE))
+ {
+ if(theDataToCompile.textures.empty()&&
+ theDataToCompile.vbos.empty())
+ {
+ FindCompileableGLObjectsVisitor visitor(theDataToCompile,
+ theTerrain.get(),
+ 0);
+ theNewMesh->accept(visitor);
+ }
+ if(!theDataToCompile.textures.empty())
+ {
+ ossim_uint32 idx = 0;
+ for(osgUtil::IncrementalCompileOperation::ContextSet::iterator itr = contexts.begin();
+ itr != contexts.end();
+ ++itr)
+ {
+ ++compileSet._numberCompileListsToCompile;
+
+ osgUtil::IncrementalCompileOperation::CompileList& cl = compileSet._compileMap[*itr];
+
+ // do textures first
+ for(TextureSetList::iterator iter = theDataToCompile.textures.begin();
+ iter!=theDataToCompile.textures.end();++iter)
+ {
+ cl.add((*iter).get());
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void ossimPlanetElevationRequest::applyToGraph()
+{
+ if((state()!=CANCELED_STATE)&&theTile.valid()&&theImage.valid()&&theNewMesh.valid())
+ {
+ osg::ref_ptr<ossimPlanetTerrainImageLayer> imageLayer = theTile->elevationLayer();
+ theTile->terrainTechnique()->setElevationMeshFrom(theNewMesh.get());
+ }
+ theNewMesh = 0;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetUtility.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetUtility.cpp
new file mode 100644
index 0000000..bf22f5d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetUtility.cpp
@@ -0,0 +1,129 @@
+#include "ossimPlanet/ossimPlanetUtility.h"
+#include <math.h>
+
+void ossimPlanetUtility::ellipsoidToXYZ( const osg::EllipsoidModel& model,
+ double latitude, double longitude, double height,
+ double &x, double &y, double &z)
+{
+ model.convertLatLongHeightToXYZ(latitude,
+ longitude,
+ height,
+ x,
+ y,
+ z);
+ x/=model.getRadiusEquator();
+ y/=model.getRadiusEquator();
+ z/=model.getRadiusEquator();
+}
+
+osg::Vec3d ossimPlanetUtility::normal(const osg::EllipsoidModel& model,
+ double x, double y, double z)
+{
+ double bSquared = model.getRadiusPolar()/model.getRadiusEquator();
+ bSquared *= bSquared;
+ return osg::Vec3d((2.0*x),
+ (2.0*y),
+ (2.0*z)/bSquared);
+}
+
+void ossimPlanetUtility::XYZToEllipsoid(const osg::EllipsoidModel& model,
+ double x, double y, double z,
+ double& latitude, double& longitude, double& height)
+{
+ x*=model.getRadiusEquator();
+ y*=model.getRadiusEquator();
+ z*=model.getRadiusEquator();
+ model.convertXYZToLatLongHeight(x,
+ y,
+ z,
+ latitude,
+ longitude,
+ height);
+}
+
+bool ossimPlanetUtility::intersectsEllipsoid(const osg::EllipsoidModel& model,
+ osg::Vec3d& intersection,
+ const osg::Vec3d& start,
+ const osg::Vec3d& end)
+{
+ osg::Vec3d startPoint = start;//*model.getRadiusEquator();
+ osg::Vec3d endPoint = end;//*model.getRadiusEquator();
+ /*
+ *Compute ellipsoid quadratics:
+ */
+// double A = model.getRadiusEquator();
+// double B = model.getRadiusPolar();
+ // double A = 1.0;
+ double B = model.getRadiusPolar()/model.getRadiusEquator();
+// double A_squared = A*A;
+ double A_squared = 1.0;
+ double B_squared = (B*B);
+ osg::Vec3d direction = endPoint-startPoint;
+ direction.normalize();
+// startPoint = startPoint + direction*.00001;
+
+ //***
+ // get the origin and direction of ray:
+ //***
+
+ //***
+ // Solve the coefficents of the quadratic formula
+ //***
+ double a = ((direction[0] * direction[0])/A_squared) +
+ ((direction[1] * direction[1])/A_squared) +
+ ((direction[2] * direction[2])/B_squared);
+
+ double b = 2.0*( ((startPoint.x()*direction.x())/A_squared) +
+ ((startPoint.y()*direction.y())/A_squared) +
+ ((startPoint.z()*direction.z())/B_squared) );
+
+ double c = ((startPoint.x()*startPoint.x())/A_squared) +
+ ((startPoint.y()*startPoint.y())/A_squared) +
+ ((startPoint.z()*startPoint.z())/B_squared) - 1.0;
+
+ //***
+ // solve the quadratic
+ //***
+ double root = b*b - 4*a*c;
+ double t;
+ if(root < 0.0)
+ {
+ return false;
+ }
+ else
+ {
+ double squareRoot = sqrt(root);
+ double t1 = (-b + squareRoot ) / (2.0*a);
+ double t2 = (-b - squareRoot ) / (2.0*a);
+
+ //***
+ // sort t1 and t2 and take the nearest intersection if they
+ // are in front of the ray.
+ //***
+ if(t2 < t1)
+ {
+ double temp = t1;
+ t1 = t2;
+ t2 = temp;
+ }
+
+ if(t1 > 0.0)
+ t = t1;
+ else
+ t = t2;
+ }
+
+ //***
+ // Now apply solved t to ray to extrapolate correct distance to intersection
+ //***
+ bool rtnval = false;
+ if (t >= 0)
+ {
+ rtnval = true;
+ intersection = start + direction*t;
+// intersection = intersection*(1.0/model.getRadiusEquator());
+ }
+
+ return rtnval;
+
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetVideoLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetVideoLayer.cpp
new file mode 100644
index 0000000..f3934d0
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetVideoLayer.cpp
@@ -0,0 +1,46 @@
+#include <ossimPlanet/ossimPlanetVideoLayer.h>
+#ifdef OSSIMPLANET_ENABLE_PREDATOR
+#include <ossimPlanet/ossimPlanetPredatorVideoLayerNode.h>
+#endif
+#include <ossimPlanet/ossimPlanet.h>
+#include <iostream>
+
+void ossimPlanetVideoLayer::traverse(osg::NodeVisitor& nv)
+{
+ if(!theEnableFlag) return;
+
+ switch(nv.getVisitorType())
+ {
+ case osg::NodeVisitor::UPDATE_VISITOR:
+ {
+ if(!thePlanet)
+ {
+ thePlanet = ossimPlanet::findPlanet(this);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ ossimPlanetLayer::traverse(nv);
+}
+
+bool ossimPlanetVideoLayer::add(const ossimFilename& file)
+{
+#ifdef OSSIMPLANET_ENABLE_PREDATOR
+ // later we will stage in a background thread but for now we will just open here for testing
+ // until we get the drawing working
+ //
+ osg::ref_ptr<ossimPlanetPredatorVideoLayerNode> node = new ossimPlanetPredatorVideoLayerNode(this);
+
+ if(node->open(file))
+ {
+ addChild(node.get());
+ return true;
+ }
+#endif
+ return false;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetViewMatrixBuilder.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetViewMatrixBuilder.cpp
new file mode 100644
index 0000000..892e4fb
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetViewMatrixBuilder.cpp
@@ -0,0 +1,615 @@
+
+#include <ossimPlanet/ossimPlanetViewMatrixBuilder.h>
+#include <ossimPlanet/ossimPlanetLsrSpaceTransform.h>
+#include <ossimPlanet/ossimPlanetPointModel.h>
+#include <ossimPlanet/mkUtils.h>
+#include <osg/io_utils>
+ossimPlanetViewMatrixBuilder::Visitor::Visitor()
+:osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+{
+}
+void ossimPlanetViewMatrixBuilder::Visitor::apply(osg::Node& node)
+{
+ ossimPlanetPointModel* pointModel = dynamic_cast<ossimPlanetPointModel*>(&node);
+ if(pointModel)
+ {
+ thePointModel = pointModel;
+ theLsrSpaceTransform = thePointModel->lsrSpace();
+ return;
+ }
+ else
+ {
+ ossimPlanetLsrSpaceTransform* lsrSpace = dynamic_cast<ossimPlanetLsrSpaceTransform*>(&node);
+ if(lsrSpace)
+ {
+ theLsrSpaceTransform = lsrSpace;
+ return;
+ }
+ }
+
+ traverse(node);
+}
+
+ossimPlanetViewMatrixBuilder::ossimPlanetViewMatrixBuilder(ossimPlanetGeoRefModel* geoRefModel)
+:theModel(geoRefModel),
+theLookAxis(LOOK_AXIS_Y),
+theFromInformationSetFlag(false),
+theFromNode(0),
+theFromPositionLLH(osg::Vec3d(0.0,0.0,0.0)),
+theFromRelativeHpr(osg::Vec3d(0.0,0.0,0.0)),
+theFromRelativeOrientationFlags(ALL_ORIENTATION),
+theFromHpr(osg::Vec3d(0.0,0.0,0.0)),
+theFromRange(0.0),
+theToInformationSetFlag(false),
+theToNode(0),
+theToPositionLLH(osg::Vec3d(0.0,0.0,0.0)),
+theToDisplacement(osg::Vec3d(0.0,0.0,0.0)),
+theToRange(0.0),
+theAttitudeHpr(osg::Vec3d(0.0,0.0,0.0)),
+theRange(0.0),
+theViewMatrix(osg::Matrixd()),
+theInverseViewMatrix(osg::Matrixd()),
+theComputeViewMatrixFlag(false)
+{
+
+}
+
+ossimPlanetViewMatrixBuilder::ossimPlanetViewMatrixBuilder(const osg::Matrixd& m, ossimPlanetGeoRefModel* geoRefModel)
+:theModel(geoRefModel),
+theLookAxis(LOOK_AXIS_Y),
+theFromInformationSetFlag(false),
+theFromNode(0),
+theFromPositionLLH(osg::Vec3d(0.0,0.0,0.0)),
+theFromRelativeHpr(osg::Vec3d(0.0,0.0,0.0)),
+theFromRelativeOrientationFlags(ALL_ORIENTATION),
+theFromHpr(osg::Vec3d(0.0,0.0,0.0)),
+theFromRange(0.0),
+theToInformationSetFlag(false),
+theToNode(0),
+theToPositionLLH(osg::Vec3d(0.0,0.0,0.0)),
+theToDisplacement(osg::Vec3d(0.0,0.0,0.0)),
+theToRange(0.0),
+theAttitudeHpr(osg::Vec3d(0.0,0.0,0.0)),
+theRange(0.0),
+theViewMatrix(osg::Matrixd()),
+theInverseViewMatrix(osg::Matrixd()),
+theComputeViewMatrixFlag(false)
+{
+ setParametersByMatrix(m);
+}
+
+ossimPlanetViewMatrixBuilder::ossimPlanetViewMatrixBuilder(const ossimPlanetViewMatrixBuilder& src)
+:theModel(src.theModel),
+theLookAxis(src.theLookAxis),
+theFromInformationSetFlag(src.theFromInformationSetFlag),
+theFromNode(src.theFromNode),
+theFromPositionLLH(src.theFromPositionLLH),
+theFromRelativeHpr(src.theFromRelativeHpr),
+theFromRelativeOrientationFlags(src.theFromRelativeOrientationFlags),
+theFromHpr(src.theFromHpr),
+theFromRange(src.theFromRange),
+theFromDisplacement(src.theFromDisplacement),
+theToInformationSetFlag(src.theToInformationSetFlag),
+theToNode(src.theToNode),
+theToPositionLLH(src.theToPositionLLH),
+theToDisplacement(src.theToDisplacement),
+theToRange(src.theToRange),
+theAttitudeHpr(src.theAttitudeHpr),
+theRange(src.theRange),
+theViewMatrix(src.theViewMatrix),
+theInverseViewMatrix(src.theInverseViewMatrix),
+theComputeViewMatrixFlag(src.theComputeViewMatrixFlag)
+{
+}
+
+ossimPlanetViewMatrixBuilder::~ossimPlanetViewMatrixBuilder()
+{
+
+}
+
+void ossimPlanetViewMatrixBuilder::setGeoRefModel(ossimPlanetGeoRefModel* model)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theModel = model;
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::updateFromLocalDisplacement(const osg::Vec3d& displacement)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromDisplacement = displacement;
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::setLookFromNodeOffset(osg::Node* node,
+ const osg::Vec3d& hpr,
+ double range,
+ int relativeOrientationFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromInformationSetFlag = false;
+ theFromNode = node;
+ if(!node||!theModel.valid()) return;
+
+ Visitor v;
+ node->accept(v);
+ theFromRange = range;
+ theFromRelativeOrientationFlags = static_cast<OrientationFlags>(relativeOrientationFlag);
+ theFromRelativeHpr = hpr;
+ theFromInformationSetFlag = false;
+ if(v.theLsrSpaceTransform.valid())
+ {
+ if(!theModel.valid())
+ {
+ theModel = v.theLsrSpaceTransform->model();
+ }
+ theFromInformationSetFlag = true;
+ theFromPositionLLH = osg::Vec3d(v.theLsrSpaceTransform->lat(),
+ v.theLsrSpaceTransform->lon(),
+ v.theLsrSpaceTransform->altitude());
+ theFromHpr = v.theLsrSpaceTransform->headingPitchRoll();
+
+ setComputeViewMatrixFlag(true);
+ }
+}
+
+void ossimPlanetViewMatrixBuilder::setLookFrom(const osg::Vec3d& llh,
+ const osg::Vec3d& hpr,
+ double range)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theFromNode = 0;
+ theFromRange = range; // we displace along the look
+ theFromPositionLLH = llh;
+ theFromInformationSetFlag = true;
+ theFromRelativeOrientationFlags = ALL_ORIENTATION;
+ theFromRelativeHpr = hpr;
+ theFromHpr = osg::Vec3d(0.0,0.0,0.0);
+ setComputeViewMatrixFlag(true);
+}
+
+osg::Vec3d ossimPlanetViewMatrixBuilder::computeFromOrientation()const
+{
+ osg::Vec3d hpr = theFromRelativeHpr;
+ if(theFromRelativeOrientationFlags&HEADING)
+ {
+ // we use the hpr of the node
+ hpr[0] += theFromHpr[0];
+ }
+ if(theFromRelativeOrientationFlags&PITCH)
+ {
+ // we use the hpr of the node
+ hpr[1] += theFromHpr[1];
+ }
+ if(theFromRelativeOrientationFlags&ROLL)
+ {
+ // we use the hpr of the node
+ hpr[2] += theFromHpr[2];
+ }
+ return hpr;
+}
+
+void ossimPlanetViewMatrixBuilder::setLookToNode(osg::Node* node)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theToNode = node;
+ theToInformationSetFlag = false;
+ if(node)
+ {
+ Visitor v;
+ node->accept(v);
+ if(v.theLsrSpaceTransform.valid())
+ {
+ theToPositionLLH = osg::Vec3d(v.theLsrSpaceTransform->lat(),
+ v.theLsrSpaceTransform->lon(),
+ v.theLsrSpaceTransform->altitude());
+ theToInformationSetFlag = true;
+ }
+ else
+ {
+ // for now set back to null since we can't do anything with it
+ theToNode = 0;
+ }
+ }
+
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::setLookTo(const osg::Vec3d& llh)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theToNode = 0;
+ theToPositionLLH = llh;
+ theToInformationSetFlag = true;
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::setLookToLocalDisplacement(const osg::Vec3d& displacement)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theToDisplacement = displacement;
+ setComputeViewMatrixFlag(true);
+}
+void ossimPlanetViewMatrixBuilder::setLookToRange(double range)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theToRange = range;
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::setRange(double range)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ theRange = range;
+ setComputeViewMatrixFlag(true);
+}
+
+double ossimPlanetViewMatrixBuilder::range()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ return theRange;
+}
+
+bool ossimPlanetViewMatrixBuilder::extractCompositedLlhHprParameters(osg::Vec3d& llh,
+ osg::Vec3d& hpr)const
+{
+ // no calculate the HPR and position of the from
+ //
+ ossimPlanetViewMatrixBuilder thisBuilder(*this);
+ ossimPlanetViewMatrixBuilder tempBuilder(theModel.get());
+ thisBuilder.setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_NEGATIVE_Z);
+ osg::Matrixd m = thisBuilder.viewMatrix();
+ osg::Vec3d eyeXyz(m(3,0), m(3,1), m(3,2));
+ theModel->xyzToLatLonHeight(eyeXyz, llh);
+ tempBuilder.setLookAxis(ossimPlanetViewMatrixBuilder::LOOK_AXIS_NEGATIVE_Z);
+ tempBuilder.setLookFrom(llh, osg::Vec3d(0.0,0.0,0.0), 0.0);
+ osg::Matrixd lsrM = tempBuilder.viewMatrix();
+ osg::Vec3d newHpr;
+ mkUtils::matrixToHpr(newHpr, lsrM, m);
+ hpr = newHpr;
+
+ return true;
+}
+
+void ossimPlanetViewMatrixBuilder::setParametersByMatrix(const osg::Matrixd& m)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(!theModel.valid())
+ {
+ // nothing to do
+ return;
+ }
+ theAttitudeHpr = osg::Vec3d(0.0,0.0,0.0);
+ theFromRelativeOrientationFlags = ALL_ORIENTATION;
+ theFromRelativeHpr = osg::Vec3d(0.0,0.0,0.0);
+ theFromRange = 0.0;
+ theFromDisplacement = osg::Vec3d(0.0,0.0,0.0);
+ theToInformationSetFlag = false;
+ theFromInformationSetFlag = true;
+ theToNode = 0;
+ theFromNode = 0;
+ theToDisplacement = osg::Vec3d(0.0,0.0,0.0);
+ theToRange = 0.0;
+ theRange = 0.0;
+ // no calculate the HPR and position of the from
+ //
+ osg::Vec3d eyeXyz(m(3,0), m(3,1), m(3,2));
+ osg::Matrixd lsrM;
+ theModel->xyzToLatLonHeight(eyeXyz, theFromPositionLLH);
+ theModel->orientationLsrMatrix(lsrM, theFromPositionLLH, 0.0, 0.0, 0.0);
+ osg::Vec3d newHpr;
+ mkUtils::matrixToHpr(newHpr, lsrM, m);
+ newHpr[1] -= 90.0;
+ newHpr[1] = ossim::wrap(newHpr[1], -180.0, 180.0);
+ theFromHpr = newHpr;
+
+
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::convertToAFromViewMatrix(bool flattenRangeFlag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(!theModel.valid())
+ {
+ // nothing to do
+ return;
+ }
+ if(flattenRangeFlag&&!theToInformationSetFlag)
+ {
+ if(theFromRange != 0.0)
+ {
+ osg::Vec3d savedAttitudeHpr = theAttitudeHpr;
+ theAttitudeHpr = osg::Vec3d(0.0,0.0,0.0);
+ setComputeViewMatrixFlag(true);
+ osg::Matrixd currentM = viewMatrix();
+ theAttitudeHpr = savedAttitudeHpr;
+ setComputeViewMatrixFlag(true);
+ osg::Matrixd lsrM;
+ osg::Vec3d eyeXyz(currentM(3,0), currentM(3,1), currentM(3,2));
+ osg::Vec3d eyeLlh;
+ theModel->xyzToLatLonHeight(eyeXyz, eyeLlh);
+ theModel->orientationLsrMatrix(lsrM, eyeLlh, 0.0, 0.0, 0.0);
+ theFromRange = 0.0;
+ theFromPositionLLH = eyeLlh;
+ osg::Vec3d newHpr;
+ mkUtils::matrixToHpr(newHpr, lsrM, currentM);
+ newHpr[1] -= 90.0;
+ newHpr[1] = ossim::wrap(newHpr[1], -180.0, 180.0);
+ // newHpr[2] = 0.0;
+ theFromHpr = newHpr;
+ }
+ }
+ else
+ {
+ osg::Vec3d newHpr;
+ osg::Vec3d toXyz;
+ theModel->latLonHeightToXyz(theToPositionLLH, toXyz);
+ osg::Vec3d savedAttitudeHpr = theAttitudeHpr;
+ theAttitudeHpr = osg::Vec3d(0.0,0.0,0.0);
+ setComputeViewMatrixFlag(true);
+ osg::Matrixd currentM = viewMatrix();
+ theAttitudeHpr = savedAttitudeHpr;
+ setComputeViewMatrixFlag(true);
+ osg::Matrixd lsrM;
+ osg::Vec3d eyeXyz(currentM(3,0), currentM(3,1), currentM(3,2));
+ osg::Vec3d eyeLlh;
+ theModel->xyzToLatLonHeight(eyeXyz, eyeLlh);
+
+ if(flattenRangeFlag)
+ {
+ theModel->orientationLsrMatrix(lsrM, eyeLlh, 0.0, 0.0, 0.0);
+ theFromRange = 0.0;
+ theFromPositionLLH = eyeLlh;
+ }
+ else
+ {
+ double range = theModel->calculateUnnormalizedLengthXyz(eyeXyz, toXyz);
+ theModel->orientationLsrMatrix(lsrM, theToPositionLLH, 0.0, 0.0, 0.0);
+ theFromRange = -range; // we displace along the look
+ theFromPositionLLH = theToPositionLLH;
+ }
+ mkUtils::matrixToHpr(newHpr, lsrM, currentM);
+
+
+ // osg::Matrixd viewM = viewMatrix();
+ newHpr[1] -= 90.0;
+ newHpr[1] = ossim::wrap(newHpr[1], -180.0, 180.0);
+ // newHpr[2] = 0.0;
+ theFromHpr = newHpr;
+ }
+ theFromRelativeOrientationFlags = ALL_ORIENTATION;
+ theFromRelativeHpr = osg::Vec3d(0.0,0.0,0.0);
+ theFromDisplacement = osg::Vec3d(0.0,0.0,0.0);
+ theToInformationSetFlag = false;
+ theFromInformationSetFlag = true;
+ theToNode = 0;
+ theFromNode = 0;
+ theRange = 0.0;
+ setComputeViewMatrixFlag(true);
+}
+
+void ossimPlanetViewMatrixBuilder::computeMatrices()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(thePropertyMutex);
+ if(!theModel) return;
+ // need to compute the view matrix
+ if(theFromInformationSetFlag)
+ {
+ osg::Matrixd tempM;
+ osg::Vec3d hpr = computeFromOrientation();
+ theModel->orientationLsrMatrix(tempM,
+ theFromPositionLLH,
+ hpr[0],
+ hpr[1],
+ hpr[2]);
+ osg::Vec3d xAxis(tempM(0,0), tempM(0,1), tempM(0,2));
+ osg::Vec3d yAxis(tempM(1,0), tempM(1,1), tempM(1,2));
+ osg::Vec3d zAxis(tempM(2,0), tempM(2,1), tempM(2,2));
+ osg::Vec3d eye(tempM(3,0), tempM(3,1), tempM(3,2));
+ osg::Vec3d newEye;
+ if(!ossim::almostEqual(theFromDisplacement.length2(), 0.0, 1e-15))
+ {
+ osg::Matrixd displacementM;
+
+ theModel->orientationLsrMatrix(displacementM,
+ theFromPositionLLH,
+ theFromHpr[0],
+ theFromHpr[1],
+ theFromHpr[2]);
+
+ // we will only displace along the axis of the orientation matrix
+ // relative to the model to solve the new eye origin
+ //
+ osg::Vec3d displacement = theFromDisplacement*theModel->getInvNormalizationScale();
+ osg::Vec3d xAxis(displacementM(0,0), displacementM(0,1), displacementM(0,2));
+ osg::Vec3d yAxis(displacementM(1,0), displacementM(1,1), displacementM(1,2));
+ osg::Vec3d zAxis(displacementM(2,0), displacementM(2,1), displacementM(2,2));
+ osg::Vec3d eye(displacementM(3,0), displacementM(3,1), displacementM(3,2));
+ newEye = (eye +
+ xAxis*displacement[0]+
+ yAxis*displacement[1]+
+ zAxis*displacement[2]);
+ }
+ else
+ {
+ newEye = eye;
+ }
+ osg::Vec3d lookVector;
+ osg::Vec3d upAxis;
+ switch(theLookAxis)
+ {
+ case LOOK_AXIS_X:
+ {
+ lookVector = (newEye + xAxis) - newEye;
+ upAxis = zAxis;
+ break;
+ }
+ case LOOK_AXIS_Y:
+ {
+ lookVector = (newEye + yAxis) - newEye;
+ upAxis = zAxis;
+ //std::cout << "HPR build = " << theFromHpr << std::endl;
+ break;
+ }
+ case LOOK_AXIS_Z:
+ {
+ lookVector = (newEye + zAxis) - newEye;
+ upAxis = yAxis;
+ break;
+ }
+ case LOOK_AXIS_NEGATIVE_X:
+ {
+ lookVector = (newEye - xAxis) - newEye;
+ upAxis = zAxis;
+ break;
+ }
+ case LOOK_AXIS_NEGATIVE_Y:
+ {
+ lookVector = (newEye - yAxis) - newEye;
+ upAxis = zAxis;
+ break;
+ }
+ case LOOK_AXIS_NEGATIVE_Z:
+ {
+ lookVector = (newEye - zAxis) - newEye;
+ upAxis = yAxis;
+ break;
+ }
+ default:
+ {
+ // for now we only support Y Axis;
+ lookVector = (newEye + zAxis) - newEye;
+ upAxis = yAxis;
+ break;
+ }
+ }
+ lookVector.normalize();
+
+ // now displace along the look axis a range value
+ //
+ newEye = newEye + lookVector*(theModel->getInvNormalizationScale()*theFromRange);
+
+ // now let's make a look at based on the orientation axis and the final eye
+ // position. We should have the center displacment and range integrated into
+ // the final look
+ //
+ if(!theToInformationSetFlag)
+ {
+ if(!ossim::almostEqual(theRange, 0.0))
+ {
+ newEye = newEye + lookVector*(theModel->getInvNormalizationScale()*theRange);
+ theInverseViewMatrix.makeLookAt(newEye, newEye + lookVector, upAxis);
+ }
+ else
+ {
+ theInverseViewMatrix.makeLookAt(newEye, newEye + lookVector, upAxis);
+ }
+ theViewMatrix.invert(theInverseViewMatrix);
+ }
+ else
+ {
+ osg::Vec3d toXyz;
+ theModel->latLonHeightToXyz(theToPositionLLH, toXyz);
+
+ double delta = (newEye-toXyz).length();
+ // sanity check
+ //
+ if(ossim::almostEqual(0.0,delta))
+ {
+ if(!ossim::almostEqual(theRange, 0.0))
+ {
+ newEye = newEye + lookVector*(theModel->getInvNormalizationScale()*theRange);
+ theInverseViewMatrix.makeLookAt(newEye, newEye + lookVector, upAxis);
+ }
+ else
+ {
+ theInverseViewMatrix.makeLookAt(newEye, newEye + lookVector, upAxis);
+ }
+ theViewMatrix.invert(theInverseViewMatrix);
+ }
+ else
+ {
+ upAxis = zAxis;
+ lookVector = toXyz-newEye;
+ lookVector.normalize();
+
+ if(!ossim::almostEqual(theToDisplacement.length2(), 0.0, 1e-15)||
+ !ossim::almostEqual(theToRange,0.0,1e-15)||
+ !ossim::almostEqual(theRange, 0.0, 1e-15))
+ {
+ osg::Vec3d displacement = theToDisplacement*theModel->getInvNormalizationScale();
+ double range = (theToRange+theRange)*theModel->getInvNormalizationScale();
+ // double range = (theToRange)*theModel->getInvNormalizationScale();
+ theInverseViewMatrix.makeLookAt(newEye, toXyz, upAxis);
+ theViewMatrix.invert(theInverseViewMatrix);
+ osg::Vec3d xAxis(theViewMatrix(0,0), theViewMatrix(0,1), theViewMatrix(0,2));
+ osg::Vec3d yAxis(theViewMatrix(1,0), theViewMatrix(1,1), theViewMatrix(1,2));
+ osg::Vec3d zAxis(-theViewMatrix(2,0), -theViewMatrix(2,1), -theViewMatrix(2,2));
+ osg::Vec3d eye(theViewMatrix(3,0), theViewMatrix(3,1), theViewMatrix(3,2));
+ newEye = (eye +
+ xAxis*displacement[0]+
+ yAxis*displacement[1]+
+ zAxis*(displacement[2]+range));
+ }
+ theInverseViewMatrix.makeLookAt(newEye, toXyz, upAxis);
+
+ theViewMatrix.invert(theInverseViewMatrix);
+ }
+ // create a forward vector to the desired look point
+ }
+
+ if(!ossim::almostEqual(theAttitudeHpr.length2(), 0.0, 1e-15))
+ {
+ // now let's apply the final orientation matrix
+ // we will see if we can integrate further in the chain so we can limit the number
+ // of inverts we have to do.
+ //
+ xAxis = upAxis^lookVector;
+ zAxis = xAxis^lookVector;
+
+ osg::Matrixd rot;
+ rot.makeIdentity();
+ rot.makeRotate(osg::DegreesToRadians(theAttitudeHpr[0]), zAxis, // heading
+ osg::DegreesToRadians(theAttitudeHpr[1]), xAxis, // pitch
+ osg::DegreesToRadians(theAttitudeHpr[2]), lookVector); // roll
+ osg::Matrixd result(theViewMatrix);
+ mkUtils::mult3x3(result, theViewMatrix, rot);
+ theViewMatrix = result;
+ theInverseViewMatrix.invert(theViewMatrix);
+ }
+
+ }
+#if 0 // debug stuff
+ {
+ osg::Vec3d xAxis(theInverseViewMatrix(0,0), theInverseViewMatrix(0,1), theInverseViewMatrix(0,2));
+ osg::Vec3d yAxis(theInverseViewMatrix(1,0), theInverseViewMatrix(1,1), theInverseViewMatrix(1,2));
+ osg::Vec3d zAxis(theInverseViewMatrix(2,0), theInverseViewMatrix(2,1), theInverseViewMatrix(2,2));
+ std::cout << "INVERSE x = " << xAxis << std::endl;
+ std::cout << "INVERSE Y = " << yAxis << std::endl;
+ std::cout << "INVERSE z = " << zAxis << std::endl;
+ }
+#endif
+ theComputeViewMatrixFlag = false;
+}
+
+
+const osg::Matrix& ossimPlanetViewMatrixBuilder::viewMatrix()const
+{
+ if(computeViewMatrixFlag())
+ {
+ computeMatrices();
+ }
+
+ return theViewMatrix;
+}
+
+const osg::Matrix& ossimPlanetViewMatrixBuilder::inverseViewMatrix()const
+{
+ if(computeViewMatrixFlag())
+ {
+ computeMatrices();
+ }
+
+ return theInverseViewMatrix;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetViewer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetViewer.cpp
new file mode 100644
index 0000000..afb1842
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetViewer.cpp
@@ -0,0 +1,1127 @@
+#include <ossimPlanet/ossimPlanetViewer.h>
+#include <ossimPlanet/ossimPlanetLookAt.h>
+#include <ossimPlanet/ossimPlanetManipulator.h>
+
+#include <ossimPlanet/ossimPlanetTextureLayerRegistry.h>
+#include <osg/CoordinateSystemNode>
+#include <osg/io_utils>
+#include <OpenThreads/ScopedLock>
+#include <osgUtil/IncrementalCompileOperation>
+
+class ossimPlanetViewerFindNodesVisitor : public osg::NodeVisitor
+{
+public:
+ ossimPlanetViewerFindNodesVisitor(const ossimString& id,
+ ossimPlanetViewer::PlanetNodeList* nodeList,
+ bool findFirstNodeOnlyFlag=false)
+ :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
+ theListIsSharedFlag(true),
+ theFindFirstNodeOnlyFlag(findFirstNodeOnlyFlag),
+ theId(id),
+ theNodeList(nodeList)
+ {
+ theNodeList->clear();
+ }
+ ossimPlanetViewerFindNodesVisitor(const ossimString& id,
+ bool findFirstNodeOnlyFlag=false)
+ :theListIsSharedFlag(false),
+ theFindFirstNodeOnlyFlag(findFirstNodeOnlyFlag),
+ theId(id),
+ theNodeList(new ossimPlanetViewer::PlanetNodeList)
+ {
+
+ }
+ virtual ~ossimPlanetViewerFindNodesVisitor()
+ {
+ if(!theListIsSharedFlag&&theNodeList&&theNodeList)
+ {
+ delete theNodeList;
+ }
+ theNodeList = 0;
+ }
+ ossimPlanetViewer::PlanetNodeList* nodeList()
+ {
+ return theNodeList;
+ }
+ const ossimPlanetViewer::PlanetNodeList* nodeList()const
+ {
+ return theNodeList;
+ }
+ virtual void apply(osg::Node& node)
+ {
+ ossimPlanetNode* planetNode = dynamic_cast<ossimPlanetNode*>(&node);
+
+ if(planetNode)
+ {
+ if(planetNode->id() == theId)
+ {
+ if(theNodeList)
+ {
+ theNodeList->push_back(planetNode);
+ }
+ }
+ }
+ // keep going even if we find a node
+ // if the flag is not set
+ //
+ if(theNodeList&&theNodeList->size() && !theFindFirstNodeOnlyFlag)
+ {
+ traverse(node);
+ }
+ }
+protected:
+ bool theListIsSharedFlag;
+ bool theFindFirstNodeOnlyFlag;
+ ossimString theId;
+ ossimPlanetViewer::PlanetNodeList* theNodeList;
+};
+
+class ossimPlanetViewer::InitializePointersVisitor : public osg::NodeVisitor
+{
+public:
+ InitializePointersVisitor(ossimPlanetViewer* viewer)
+ :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
+ theViewer(viewer)
+ {
+ if(theViewer)
+ {
+ if(theViewer->thePlanet.valid())
+ {
+ theViewer->thePlanet->setComputeIntersectionFlag(true);
+ theViewer->thePlanet->removeCallback(theViewer->theCallback.get());
+ }
+ theViewer->thePlanet = 0;
+ theViewer->theTerrainLayer = 0;
+ theViewer->theAnnotationLayer = 0;
+ }
+ }
+ virtual void apply(osg::Node& node)
+ {
+
+ if(theViewer)
+ {
+ ossimPlanet* planet = dynamic_cast<ossimPlanet*>(&node);
+ ossimPlanetLand* landLayer = dynamic_cast<ossimPlanetLand*>(&node);
+ ossimPlanetTerrain* terrainLayer = dynamic_cast<ossimPlanetTerrain*>(&node);
+ ossimPlanetAnnotationLayer* annotationLayer = dynamic_cast<ossimPlanetAnnotationLayer*>(&node);
+ ossimPlanetKmlLayer* kmlLayer = dynamic_cast<ossimPlanetKmlLayer*>(&node);
+ if(planet)
+ {
+ if(!theViewer->thePlanet.valid())
+ {
+ theViewer->thePlanet = planet;
+ if(theViewer->theEphemerisLayer.valid())
+ {
+ theViewer->theEphemerisLayer->setModel(planet->model().get());
+ }
+ if(theViewer->thePlanet.valid())
+ {
+ // the viewer will manage setting a valid intersection point
+ // for any who need it. This is the current intersection for
+ // current traverse.
+ //
+ theViewer->thePlanet->setComputeIntersectionFlag(false);
+ theViewer->thePlanet->addCallback(theViewer->theCallback.get());
+ }
+ }
+ }
+ else if(kmlLayer)
+ {
+ theViewer->theKmlLayer = kmlLayer;
+ }
+ else if(annotationLayer)
+ {
+ theViewer->theAnnotationLayer = annotationLayer;
+ }
+ else if(terrainLayer)
+ {
+ theViewer->theTerrainLayer = terrainLayer;
+ }
+ else if(landLayer)
+ {
+ theViewer->theTerrainLayer = landLayer;
+ }
+ if(!theViewer->theAnnotationLayer.valid() ||
+ !(theViewer->theTerrainLayer.valid()||theViewer->thePlanet.valid()))
+ {
+ traverse(node);
+ }
+ }
+ }
+
+protected:
+ ossimPlanetViewer* theViewer;
+};
+
+void ossimPlanetViewer::NodeListener::nodeAdded(osg::Node* node)
+{
+ ossimPlanetLand* land = dynamic_cast<ossimPlanetLand*>(node);
+ ossimPlanetTerrain* terrain = dynamic_cast<ossimPlanetTerrain*>(node);
+ if(land)
+ {
+ if(!theViewer->theTerrainLayer.valid())
+ {
+ theViewer->theTerrainLayer = land;
+ }
+ }
+ else if(terrain)
+ {
+ if(!theViewer->theTerrainLayer.valid())
+ {
+ theViewer->theTerrainLayer = terrain;
+ }
+ }
+ else
+ {
+ ossimPlanetAnnotationLayer* annotationLayer = dynamic_cast<ossimPlanetAnnotationLayer*>(node);
+ if(annotationLayer)
+ {
+ if(!theViewer->theAnnotationLayer.valid())
+ {
+ theViewer->theAnnotationLayer = annotationLayer;
+ }
+ }
+ else
+ {
+ ossimPlanetKmlLayer* kmlLayer = dynamic_cast<ossimPlanetKmlLayer*>(node);
+ if(kmlLayer)
+ {
+ theViewer->theKmlLayer = kmlLayer;
+ }
+ }
+ }
+}
+
+void ossimPlanetViewer::NodeListener::nodeRemoved(osg::Node* node)
+{
+ if(node == theViewer->theTerrainLayer.get())
+ {
+ theViewer->theTerrainLayer = 0;
+ }
+ else if(node == theViewer->theAnnotationLayer.get())
+ {
+ theViewer->theAnnotationLayer = 0;
+ }
+}
+
+void ossimPlanetViewer::NodeListener::needsRedraw(ossimPlanetNode* node)
+{
+ if(theViewer)
+ {
+ theViewer->requestRedraw();
+ }
+}
+
+
+ossimPlanetNode* ossimPlanetViewer::PickObject::firstPlanetNode()
+{
+ ossimPlanetNode* result = 0;
+ if(theNodePath.empty()) return result;
+ ossim_int32 idx=0;
+ for(idx = theNodePath.size()-1; ((idx >=0)&&(!result)); --idx)
+ {
+ result = dynamic_cast<ossimPlanetNode*>(theNodePath[idx].get());
+ }
+
+ return result;
+}
+
+#if 0
+void ossimPlanetViewer::Renderer::flushAndCompile(double currentElapsedFrameTime,
+ osgUtil::SceneView* sceneView,
+ osgDB::DatabasePager* databasePager,
+ osg::GraphicsThread* compileThread)
+{
+ osg::Timer_t t = osg::Timer::instance()->tick();
+ osgViewer::Renderer::flushAndCompile(currentElapsedFrameTime, sceneView, databasePager, compileThread);
+ double delta = osg::Timer::instance()->delta_s(t, osg::Timer::instance()->tick());
+ if(theCallback.valid())
+ {
+ theCallback->flushAndCompile(currentElapsedFrameTime + delta,
+ sceneView,
+ databasePager,
+ compileThread);
+ }
+}
+
+void ossimPlanetViewer::DrawCallback::operator () (osg::RenderInfo& renderInfo) const
+{
+ if(!theViewer) return;
+ if(theViewer->terrainLayer()&&renderInfo.getState())
+ {
+ //double delta = osg::Timer::instance()->delta_s(theViewer->theFrameStartTimeStamp,
+ // osg::Timer::instance()->tick());
+ theViewer->terrainLayer()->compileGLObjects(*renderInfo.getState(),
+ theViewer->terrainLayer()->minimumTimeToCompilePerFrame());
+ }
+}
+
+void ossimPlanetViewer::FlushAndCompileCallback::flushAndCompile(double currentElapsedFrameTime,
+ osgUtil::SceneView* sceneView,
+ osgDB::DatabasePager* databasePager,
+ osg::GraphicsThread* compileThread)
+{
+ if(theViewer)
+ {
+ if(theViewer->terrainLayer())
+ {
+ // let's calculate based on target frame rate later. For now give
+ // 2 milliseconds
+ //
+ theViewer->terrainLayer()->compileGLObjects(*(sceneView->getState()), .002);
+ }
+ }
+}
+#endif
+
+ossimPlanetViewer::ossimPlanetViewer()
+:osgViewer::Viewer()
+{
+ init();
+}
+
+ossimPlanetViewer::ossimPlanetViewer(osg::ArgumentParser& arguments)
+:osgViewer::Viewer(arguments)
+{
+ init();
+}
+
+ossimPlanetViewer::ossimPlanetViewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop)
+:osgViewer::Viewer(viewer, copyop)
+{
+ init();
+}
+
+ossimPlanetViewer::~ossimPlanetViewer()
+{
+ if(thePlanet.valid())
+ {
+ thePlanet->removeCallback(theCallback.get());
+ }
+ thePlanet = 0;
+}
+
+void ossimPlanetViewer::init()
+{
+ theRootNode = new osg::Group();
+ theRootNode->setUpdateCallback(new ossimPlanetTraverseCallback);
+ theRootNode->setEventCallback(new ossimPlanetTraverseCallback);
+ theRootNode->setCullCallback(new ossimPlanetTraverseCallback);
+
+// getCamera()->setPreDrawCallback(new ossimPlanetViewer::DrawCallback(this));
+ setThreadSafeRefUnref(true);
+ osgDB::DatabasePager* pager = osgDB::DatabasePager::create();
+ setDatabasePager(pager);
+ theUpdateVisitor = new ossimPlanetUpdateVisitor();
+ //theUpdateVisitor->setDatabaseRequestHandler(pager);
+ setUpdateVisitor(theUpdateVisitor.get());
+ theCallback = new ossimPlanetViewer::NodeListener(this);
+ theCurrentCamera = new ossimPlanetLookAt;
+ theCurrentLookAt = new ossimPlanetLookAt;
+ getCamera()->setClearColor(osg::Vec4(0.0,0.0,0.0,1.0));
+ //getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ //getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
+ //getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
+ theRedrawFlag = false;
+ theContinousUpdateFlag = false;
+ theIntersectWithMasterIfNotWithinAnyViewFlag = false;
+ theCalculateNearFarRatioFlag = true;
+
+ //setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation());
+
+}
+
+void ossimPlanetViewer::setTerrainMaxNumberOfOperationsToApplyToGraphPerFrame(ossim_uint32 value)
+{
+ ossimPlanetTerrain* terrain = dynamic_cast<ossimPlanetTerrain*>(theTerrainLayer.get());
+
+ if(terrain)
+ {
+ terrain->setMaxNumberOfOperationsToApplyToGraphPerFrame(value);
+ }
+}
+
+ossimPlanetManipulator* ossimPlanetViewer::planetManipulator()
+{
+ return dynamic_cast<ossimPlanetManipulator*>(getCameraManipulator());
+}
+
+ossimPlanetTerrain* ossimPlanetViewer::terrainLayer()
+{
+ return dynamic_cast<ossimPlanetTerrain*>(theTerrainLayer.get());
+}
+
+ossimPlanetAnnotationLayer* ossimPlanetViewer::annotationLayer()
+{
+ return theAnnotationLayer.get();
+}
+
+ossimPlanetKmlLayer* ossimPlanetViewer::kmlLayer()
+{
+ return theKmlLayer.get();
+}
+
+void ossimPlanetViewer::addEphemeris(ossim_uint32 memberBitMask)
+{
+ if(!theEphemerisLayer.valid())
+ {
+ if(getLight())
+ {
+ theSavedLight = (osg::Light*)getLight()->clone(osg::CopyOp::DEEP_COPY_ALL);
+ }
+ ossimPlanet* tempPlanet = new ossimPlanet;
+ tempPlanet->setComputeIntersectionFlag(false);
+ theEphemerisRoot = tempPlanet;
+ theEphemerisLayer = new ossimPlanetEphemeris();
+ theEphemerisLayer->setRoot(theRootNode.get());
+ theEphemerisLayer->setMembers(memberBitMask);
+// planet()->addChild(theEphemerisLayer.get());
+ tempPlanet->addChild(theEphemerisLayer.get());
+ theRootNode->addChild(tempPlanet);
+ theEphemerisCamera = new osg::Camera;
+ theEphemerisCamera->setProjectionResizePolicy(getCamera()->getProjectionResizePolicy());
+ theEphemerisCamera->setClearColor(getCamera()->getClearColor());
+ theEphemerisCamera->setRenderOrder(osg::Camera::PRE_RENDER);
+ theEphemerisCamera->setRenderTargetImplementation( getCamera()->getRenderTargetImplementation() );
+ // theEphemerisCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ // getCamera()->setClearMask(getCamera()->getClearMask() & ~GL_COLOR_BUFFER_BIT & ~GL_DEPTH_BUFFER_BIT);
+ theEphemerisCamera->setClearMask(GL_COLOR_BUFFER_BIT);
+ getCamera()->setClearMask(getCamera()->getClearMask() & ~GL_COLOR_BUFFER_BIT);
+ if(getCamera()->getViewport())
+ {
+ theEphemerisCamera->setViewport(new osg::Viewport(*getCamera()->getViewport()));
+ }
+ else
+ {
+ theEphemerisCamera->setViewport(new osg::Viewport());
+ }
+ addSlave(theEphemerisCamera.get(), false);
+ theEphemerisLayer->setCamera(theEphemerisCamera.get());
+ theEphemerisCamera->setEventCallback(new ossimPlanetTraverseCallback());
+ theEphemerisCamera->setUpdateCallback(new ossimPlanetTraverseCallback());
+ theEphemerisCamera->setCullCallback(new ossimPlanetTraverseCallback());
+ //theEphemerisCamera->addChild(theRootNode.get());
+ //getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ //theEphemerisCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ //double fov, aspectRatio, near, far;
+ //osg::Matrixd& m = getCamera()->getProjectionMatrix();
+ //m.getPerspective(fov, aspectRatio, near, far);
+ //theEphemerisCamera->setProjectionMatrixAsPerspective(fov, aspectRatio, .2, 5.0);
+ //getCamera()->setProjectionMatrixAsPerspective(fov, aspectRatio, .0000001, .2);
+ }
+}
+
+void ossimPlanetViewer::removeEphemeris()
+{
+ if(theEphemerisLayer.valid())
+ {
+ if(theRootNode->getNumChildren() > 1)
+ {
+ theRootNode->removeChild(1, theRootNode->getNumChildren());
+ }
+ theEphemerisLayer = 0;
+ theEphemerisRoot = 0;
+ int slaveCameraIdx = findSlaveIndexForCamera(theEphemerisCamera.get());
+ if(slaveCameraIdx >= 0)
+ {
+ removeSlave(slaveCameraIdx);
+ theEphemerisCamera = 0;
+ }
+ getCamera()->setClearMask(getCamera()->getClearMask()|GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ //setLight(new osg::Light());
+ requestRedraw();
+ }
+}
+
+ossimPlanetEphemeris* ossimPlanetViewer::ephemeris()
+{
+ return theEphemerisLayer.get();
+}
+
+void ossimPlanetViewer::requestRedraw()
+{
+ setRedrawFlag(true);
+}
+
+void ossimPlanetViewer::requestContinuousUpdate(bool needed)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ theContinousUpdateFlag=needed;
+}
+
+void ossimPlanetViewer::requestWarpPointer(float x,float y)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ theWarpPointerFlag = true; theWarpX=x; theWarpY=y;
+}
+
+bool ossimPlanetViewer::getAndSetRedrawFlag(bool newValue)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ bool result = theRedrawFlag;
+ theRedrawFlag = newValue;
+ return result;
+}
+
+bool ossimPlanetViewer::getRedrawFlag()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ return theRedrawFlag;
+}
+
+void ossimPlanetViewer::setRedrawFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ theRedrawFlag=flag;
+}
+
+bool ossimPlanetViewer::redrawFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ return theRedrawFlag;
+}
+
+void ossimPlanetViewer::setContinuousUpdateFlag(bool flag)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ theContinousUpdateFlag=flag;
+}
+
+bool ossimPlanetViewer::continuousUpdateFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ return theContinousUpdateFlag;
+}
+
+bool ossimPlanetViewer::warpPointerFlag()const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ return theWarpPointerFlag;
+}
+
+void ossimPlanetViewer::getWarpPoints(float& x, float& y)const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theActionAdapterMutex);
+ x=theWarpX;
+ y=theWarpY;
+}
+
+void ossimPlanetViewer::setSceneData(osg::Node* p)
+{
+ InitializePointersVisitor initializePointersVisitor(this);
+ theRootNode->removeChildren(0, theRootNode->getNumChildren());
+ if(p)
+ {
+ p->accept(initializePointersVisitor);
+ theRootNode->addChild(p);
+ if(theEphemerisLayer.valid())
+ {
+ ossimPlanet* tempPlanet = new ossimPlanet;
+ tempPlanet->addChild(theEphemerisLayer.get());
+ tempPlanet->setComputeIntersectionFlag(false);
+ theRootNode->addChild(tempPlanet);
+ }
+ }
+ osgViewer::Viewer::setSceneData(theRootNode.get());
+ requestRedraw();
+}
+
+ossimPlanet* ossimPlanetViewer::planet()
+{
+ return thePlanet.get();
+}
+
+const ossimPlanet* ossimPlanetViewer::planet()const
+{
+ return thePlanet.get();
+}
+
+const ossimPlanetGeoRefModel* ossimPlanetViewer::model()const
+{
+ if(thePlanet.get())
+ {
+ return thePlanet->model().get();
+ }
+
+ return 0;
+}
+
+ossimPlanetGeoRefModel* ossimPlanetViewer::model()
+{
+ if(thePlanet.get())
+ {
+ return thePlanet->model().get();
+ }
+
+ return 0;
+}
+
+void ossimPlanetViewer::advance(double simulationTime)
+{
+ theFrameStartTimeStamp = osg::Timer::instance()->tick();
+ osgViewer::Viewer::advance(simulationTime);
+}
+
+void ossimPlanetViewer::eventTraversal()
+{
+ osgViewer::Viewer::eventTraversal();
+}
+
+void ossimPlanetViewer::updateTraversal()
+{
+ ossimPlanetTerrain* terrain = dynamic_cast<ossimPlanetTerrain*>(terrainLayer());
+ if(terrain&&!terrain->getDatabasePager()) terrain->setDatabasePager(getDatabasePager());
+
+ if(!mkUtils::almostEqual(theCurrentViewMatrix,
+ getCamera()->getViewMatrix()))
+ {
+ theCurrentViewMatrix = getCamera()->getViewMatrix();
+ theCurrentViewMatrixInverse = theCurrentViewMatrix.inverse(theCurrentViewMatrix);
+ computeCurrentCameraInfo();
+ const ossimPlanetGeoRefModel* landModel = model();
+
+ // let's do a crude normalize distance to do an estimate NearFarRatio
+ //
+ if(getCamera()&&landModel&&theCurrentLookAt.valid()&&theCurrentCamera.valid()&&theCalculateNearFarRatioFlag)
+ {
+ double dist = ossim::min(theCurrentLookAt->range(),
+ theCurrentCamera->altitude())/osg::WGS_84_RADIUS_EQUATOR;
+ double t = log(1+dist);
+ t = ossim::clamp(t, 0.0, 1.0);
+ double ratio = .1*(t) + (.0000001)*(1.0-t);
+ getCamera()->setNearFarRatio(ossim::min(.001, ratio));
+ }
+ notifyViewChanged();
+ }
+ osgViewer::Viewer::updateTraversal();
+ if(theEphemerisCamera.valid())
+ {
+ if(theEphemerisCamera.valid())
+ {
+ theEphemerisCamera->setGraphicsContext(getCamera()->getGraphicsContext());
+ theEphemerisCamera->setRenderTargetImplementation( getCamera()->getRenderTargetImplementation() );
+ }
+ osg::Viewport* viewport = getCamera()->getViewport();
+ osg::Viewport* ephViewport = theEphemerisCamera->getViewport();
+ if(viewport&&ephViewport)
+ {
+ if(!ossim::almostEqual(viewport->x(), ephViewport->x())||
+ !ossim::almostEqual(viewport->y(), ephViewport->y())||
+ !ossim::almostEqual(viewport->width(), ephViewport->width())||
+ !ossim::almostEqual(viewport->height(), ephViewport->height()))
+ {
+ ephViewport->setViewport(viewport->x(),
+ viewport->y(),
+ viewport->width(),
+ viewport->height());
+ }
+ }
+ theEphemerisCamera->setProjectionMatrix(getCamera()->getProjectionMatrix());
+ theEphemerisCamera->setViewMatrix(getCamera()->getViewMatrix());
+ }
+ bool databasePagerHasRequests = getDatabasePager()?getDatabasePager()->requiresUpdateSceneGraph():false;//||
+ //getDatabasePager()->requiresCompileGLObjects()):false;
+ if(databasePagerHasRequests)
+ {
+ requestRedraw();
+ }
+
+}
+
+bool ossimPlanetViewer::addAnnotation(osg::ref_ptr<ossimPlanetAnnotationLayerNode> annotation)
+{
+ bool result = false;
+
+ if(theAnnotationLayer.valid())
+ {
+ result = theAnnotationLayer->addChild(annotation.get());
+ }
+
+ return result;
+}
+
+bool ossimPlanetViewer::addImageTexture(osg::ref_ptr<ossimPlanetTextureLayer> imageTexture)
+{
+ bool result = false;
+
+ if(theTerrainLayer.valid()&&imageTexture.valid())
+ {
+ ossimPlanetTerrain* terrain = dynamic_cast<ossimPlanetTerrain*>(theTerrainLayer.get());
+ if(terrain)
+ {
+ if(terrain->numberOfTextureLayers() > 0)
+ {
+ ossimPlanetTextureLayerGroup* group = terrain->textureLayer(0)->asGroup();
+ if(group)
+ {
+ result = group->addTop(imageTexture.get());
+ }
+ }
+ }
+ else
+ {
+ ossimPlanetLand* land = dynamic_cast<ossimPlanetLand*>(theTerrainLayer.get());
+ if(land)
+ {
+ result = land->referenceLayer()->addTop(imageTexture.get());
+ }
+ }
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetTextureLayer> ossimPlanetViewer::addImageTexture(const ossimString& file)
+{
+ osg::ref_ptr<ossimPlanetTextureLayer> layer = ossimPlanetTextureLayerRegistry::instance()->createLayer(file);
+
+ if(!addImageTexture(layer.get()))
+ {
+ layer = 0;
+ }
+
+ return layer.get();
+}
+
+bool ossimPlanetViewer::addElevation(osg::ref_ptr<ossimPlanetElevationDatabase> database, bool sortFlag)
+{
+ bool result = false;
+
+ if(theTerrainLayer.valid()&&database.valid())
+ {
+ result = true;
+ ossimPlanetTerrain* terrain = dynamic_cast<ossimPlanetTerrain*>(theTerrainLayer.get());
+ if(terrain)
+ {
+ result = terrain->addElevation(database.get(), sortFlag);
+ }
+ else
+ {
+ ossimPlanetTerrain* land = dynamic_cast<ossimPlanetTerrain*>(theTerrainLayer.get());
+ if(land)
+ {
+ result = land->addElevation(database.get(), sortFlag);
+ }
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetViewer::addKml(const ossimFilename& file)
+{
+ if(theKmlLayer.valid())
+ {
+ theKmlLayer->addKml(file);
+ }
+}
+
+void ossimPlanetViewer::computeCurrentCameraInfo()
+{
+ const ossimPlanetGeoRefModel* landModel = model();
+ if(!landModel) return;
+
+ // First solve the camera in lat lon hgt and roll pitch heading format
+ //
+ osg::Matrixd eyeLsrMatrix;
+ osg::Vec3d eyeLlh;
+ osg::Vec3d hpr;
+ osg::Vec3d eye = osg::Vec3d(0.0,0.0,0.0)*theCurrentViewMatrixInverse;
+ landModel->inverse(eye, eyeLlh);
+ landModel->lsrMatrix(eyeLlh, eyeLsrMatrix);
+ mkUtils::matrixToHpr(hpr, eyeLsrMatrix, theCurrentViewMatrixInverse);
+ theCurrentCamera->setAll(eyeLlh[0], eyeLlh[1], eyeLlh[2],
+ hpr[0], hpr[1], hpr[2],
+ 0.0, ossimPlanetAltitudeMode_ABSOLUTE);
+
+ // now compute the current lookat point
+ // if no intersection then we will fake one by extruding a lookat range meters out
+ // from current line of site
+ osg::Vec3d llh;
+ osg::Viewport* viewPort = getCamera()->getViewport();
+ if(!viewPort) return;
+ double midX=(viewPort->x()+(viewPort->width()/2.0));
+ double midY=(viewPort->y()+(viewPort->height()/2.0));
+
+ // if we do not intersect then use the range from the previous look at and create a point
+ if(!getLatLonHeightAtWindowCoordinate(llh, midX, midY))
+ {
+ osg::Vec3d origin, ray;
+ if(makeRayAtWindowCoordinate(origin, ray, midX, midY))
+ {
+ osg::Vec3d pt = origin + ray*(theCurrentLookAt->range()/landModel->getNormalizationScale());
+ landModel->inverse(pt, llh);
+ }
+ }
+ osg::Matrixd losLsrMatrix;
+ osg::Vec3d tempHpr;
+ landModel->orientationLsrMatrix(losLsrMatrix, llh, 0.0, 0.0, 0.0);
+
+ mkUtils::matrixToHpr(tempHpr, losLsrMatrix, theCurrentViewMatrixInverse);
+ osg::Vec3d eyeXyz;
+ osg::Vec3d losXyz;
+ landModel->forward(llh, losXyz);
+ double range = (losXyz-eye).length()*landModel->getNormalizationScale();
+
+ theCurrentLookAt->setAll(llh[0], llh[1], llh[2],
+ tempHpr[0], tempHpr[1], tempHpr[2],
+ range, ossimPlanetAltitudeMode_ABSOLUTE);
+
+
+#if 0
+ if(thePlanet.valid())
+ {
+ thePlanet->setLookAt(theCurrentLookAt.get());
+ thePlanet->setEyePosition(theCurrentCamera.get());
+ }
+#endif
+ // std::cout << "<lat,lon,hgt> = <" << theCurrentLookAt->lat() << ", " << theCurrentLookAt->lon() << ", " << theCurrentLookAt->altitude() << ">" << std::endl
+ // << "<h, p, r> = <" << theCurrentLookAt->heading() << ", " << theCurrentLookAt->pitch() << ", " << theCurrentLookAt->roll() << ">" << std::endl
+ // << "range = " << theCurrentLookAt->range() << std::endl;
+}
+
+void ossimPlanetViewer::findNodesWithId(ossimPlanetViewer::PlanetNodeList& nodeList,
+ const ossimString& id)
+{
+ ossimPlanetViewerFindNodesVisitor visitor(id, &nodeList, false);
+
+ if(getSceneData())
+ {
+ getSceneData()->accept(visitor);
+ }
+}
+
+osg::ref_ptr<ossimPlanetNode> ossimPlanetViewer::findFirstNodeWithId(const ossimString& id)
+{
+ osg::ref_ptr<ossimPlanetNode> result = 0;
+ ossimPlanetViewer::PlanetNodeList nodeList;
+ ossimPlanetViewerFindNodesVisitor visitor(id, &nodeList, true);
+
+ if(getSceneData())
+ {
+ getSceneData()->accept(visitor);
+ }
+
+ if(nodeList.size())
+ {
+ result = nodeList[0].get();
+ }
+
+ return result;
+}
+
+bool ossimPlanetViewer::makeRayAtWindowCoordinate(osg::Vec3d& origin,
+ osg::Vec3d& ray,
+ double wx, double wy)
+{
+ float local_x = wx, local_y = wy;
+ osg::Camera* camera = const_cast<osg::Camera*>(getCameraContainingPosition(wx, wy, local_x, local_y));
+ if (!camera) camera = getCamera();
+ return makeRayAtWindowCoordinate(origin, ray, camera, local_x, local_x);
+}
+
+bool ossimPlanetViewer::makeRayAtWindowCoordinate(osg::Vec3d& origin,
+ osg::Vec3d& ray,
+ osg::Camera* camera,
+ double wx, double wy)
+{
+ osg::Vec3d eye(0.0,0.0,0.0);
+ osg::Vec3d center(0.0,0.0,0.0);
+ osg::Vec3d up(0.0,0.0,0.0);
+ osg::Vec3d direction;
+ double fov;
+ double aspectRatio;
+ double znear;
+ double zfar;
+ osg::Matrixd pm = camera->getProjectionMatrix();
+ ray[0] = 0;
+ ray[1] = 0;
+ ray[2] = 0;
+
+ if(!pm.getPerspective(fov, aspectRatio, znear, zfar))
+ {
+ return false;
+ }
+ camera->getViewMatrixAsLookAt(eye, center, up, 1000.0);
+ osg::Matrixd iv = camera->getViewMatrix();
+
+ const osg::ref_ptr<osg::Viewport> viewport = camera->getViewport();
+ osg::Matrix wm;
+ wm.invert(viewport->computeWindowMatrix());
+ osg::Vec3d normalizedPoint = osg::Vec3d(wx,wy,0.0)*wm;
+
+ double angleY = (fov*.5)*normalizedPoint[1];
+ double angleX = (fov*.5)*normalizedPoint[0]*aspectRatio;
+ direction = center - eye;
+ direction.normalize();
+ osg::Vec3d crossVec = direction^up;
+ osg::Vec3d newUp = crossVec^direction;
+ osg::Matrixd m = (osg::Matrixd::rotate(-angleX*(M_PI/180.0), newUp)*
+ osg::Matrixd::rotate(angleY*(M_PI/180.0), crossVec));
+ ray = direction*m;
+ origin = eye;
+
+ return true;
+}
+
+bool ossimPlanetViewer::pickAtWindowCoordinate(PickList& result,
+ double wx, double wy,
+ osg::Node::NodeMask traversalMask)
+{
+ result.clear();
+
+ osgUtil::LineSegmentIntersector::Intersections intersections;
+ if (computeIntersections(wx, wy, intersections, traversalMask))
+ {
+ osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
+
+ while(hitr != intersections.end())
+ {
+ osg::Vec3d wpt = hitr->getWorldIntersectPoint();
+ osg::Vec3d llh;
+ if(model())
+ {
+ model()->inverse(wpt, llh);
+ }
+
+ result.push_back(new PickObject(hitr->nodePath, hitr->getLocalIntersectPoint(), hitr->getWorldIntersectPoint(), llh));
+ ++hitr;
+ }
+ }
+
+ return !result.empty();
+}
+
+bool ossimPlanetViewer::getLatLonHeightAtWindowCoordinate(osg::Vec3d& llh,
+ double wx, double wy,
+ osg::Node::NodeMask traversalMask)
+{
+ bool resultFlag = false;
+ osgUtil::LineSegmentIntersector::Intersections intersections;
+ if (computeIntersections(wx, wy, intersections, traversalMask))
+ {
+ osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
+
+ if(hitr != intersections.end())
+ {
+ osg::Vec3d wpt = hitr->getWorldIntersectPoint();
+ if(model())
+ {
+ model()->inverse(wpt, llh);
+ resultFlag = true;
+ }
+ }
+ }
+
+ return resultFlag;
+}
+
+void ossimPlanetViewer::notifyViewChanged()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theCallbackListMutex);
+ if(theBlockCallbacksFlag) return;
+ ossim_uint32 idx = 0;
+ ossim_uint32 upper = theCallbackList.size();
+
+ for(idx = 0; idx < upper; ++idx)
+ {
+ if(theCallbackList[idx]->enableFlag())
+ {
+ theCallbackList[idx]->viewChanged(this);
+ }
+ }
+
+}
+
+
+#if 0
+bool ossimPlanetViewer::AddHudOverlay(osg::ref_ptr<osg::Node> hudNode)
+{
+ bool result = false;
+ if(thePlanet.valid())
+ {
+ result = true;
+
+ hudNode->getOrCreateStateSet()->setRenderBinDetails(11,"RenderBin");
+ theHudOverlayList.push_back(hudNode.get());
+
+ thePlanet->addChild(hudNode.get());
+ }
+
+ return result;
+}
+
+ossim_uint32 ossimPlanetViewer::getNumberOfHudOverlays()const
+{
+ return static_cast<ossim_uint32>(theHudOverlayList.size());
+}
+#endif
+
+const osg::Camera* ossimPlanetViewer::forceAdjustToMasterCamera(float x, float y, float& local_x, float& local_y) const
+{
+
+ const osg::Camera* result = _camera.get(); // get and use the master camera
+ if(!result) return 0;
+ const osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
+ const osgViewer::GraphicsWindow* gw = dynamic_cast<const osgViewer::GraphicsWindow*>(eventState->getGraphicsContext());
+
+ bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
+
+ double epsilon = 0.5;
+
+ if (_camera->getGraphicsContext() &&
+ (!gw || _camera->getGraphicsContext()==gw) &&
+ _camera->getViewport())
+ {
+ const osg::Viewport* viewport = _camera->getViewport();
+
+ double new_x = x;
+ double new_y = y;
+
+ if (!gw)
+ {
+ new_x = static_cast<double>(_camera->getGraphicsContext()->getTraits()->width) * (x - eventState->getXmin())/(eventState->getXmax()-eventState->getXmin());
+ new_y = view_invert_y ?
+ static_cast<double>(_camera->getGraphicsContext()->getTraits()->height) * (1.0 - (y- eventState->getYmin())/(eventState->getYmax()-eventState->getYmin())) :
+ static_cast<double>(_camera->getGraphicsContext()->getTraits()->height) * (y - eventState->getYmin())/(eventState->getYmax()-eventState->getXmin());
+ }
+
+ // lets still allow for valid camera positioning even if outside the frustum if no camera is found
+ if (viewport)
+ {
+ local_x = new_x;
+ local_y = new_y;
+
+ result = _camera.get();
+ }
+ }
+
+ return result;
+}
+
+#if 1
+/** Compute intersections between a ray through the specified master cameras window/eye coords and a specified node.
+ * Note, when a master cameras has slaves and no viewport itself its coordinate frame will be in clip space i.e. -1,-1 to 1,1,
+ * while if its has a viewport the coordintates will be relative to its viewport dimensions.
+ * Mouse events handled by the view will automatically be attached into the master camera window/clip coords so can be passed
+ * directly on to the computeIntersections method. */
+bool ossimPlanetViewer::computeIntersections(float x,
+ float y,
+ osgUtil::LineSegmentIntersector::Intersections& intersections,
+ osg::Node::NodeMask traversalMask)
+{
+ if (!_camera.valid()) return false;
+
+ float local_x, local_y = 0.0;
+ const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
+ if (!camera)
+ {
+ if(theIntersectWithMasterIfNotWithinAnyViewFlag)
+ {
+ camera = forceAdjustToMasterCamera(x, y, local_x, local_y);
+ if(!camera) return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
+ osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
+ osg::Vec3d adjustedStart(picker->getStart());
+#if 0
+ if(thePlanet.valid())
+ {
+ adjustedStart[2]-=(5*thePlanet->model()->getInvNormalizationScale());
+ }
+ picker->setStart(adjustedStart);
+#endif
+ osgUtil::IntersectionVisitor iv(picker.get());
+ iv.setTraversalMask(traversalMask);
+ iv.setUseKdTreeWhenAvailable(true);
+
+ const_cast<osg::Camera*>(camera)->accept(iv);
+
+ if (picker->containsIntersections())
+ {
+ intersections = picker->getIntersections();
+ return true;
+ }
+ intersections.clear();
+ return false;
+}
+
+/** Compute intersections between a ray through the specified master cameras window/eye coords and a specified nodePath's subgraph. */
+bool ossimPlanetViewer::computeIntersections(float x,
+ float y,
+ const osg::NodePath& nodePath,
+ osgUtil::LineSegmentIntersector::Intersections& intersections,
+ osg::Node::NodeMask traversalMask)
+{
+ if (!_camera.valid() || nodePath.empty()) return false;
+
+ float local_x, local_y = 0.0;
+ const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
+ if (!camera)
+ {
+ if(theIntersectWithMasterIfNotWithinAnyViewFlag)
+ {
+ camera = forceAdjustToMasterCamera(x, y, local_x, local_y);
+ if(!camera) return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ osg::Matrixd matrix;
+ if (nodePath.size()>1)
+ {
+ osg::NodePath prunedNodePath(nodePath.begin(),nodePath.end()-1);
+ matrix = osg::computeLocalToWorld(prunedNodePath);
+ }
+
+ matrix.postMult(camera->getViewMatrix());
+ matrix.postMult(camera->getProjectionMatrix());
+
+ double zNear = -1.0;
+ double zFar = 1.0;
+ if (camera->getViewport())
+ {
+ matrix.postMult(camera->getViewport()->computeWindowMatrix());
+ zNear = 0.0;
+ zFar = 1.0;
+ }
+
+ osg::Matrixd inverse;
+ inverse.invert(matrix);
+
+ osg::Vec3d startVertex = osg::Vec3d(local_x,local_y,zNear) * inverse;
+ osg::Vec3d endVertex = osg::Vec3d(local_x,local_y,zFar) * inverse;
+
+ osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::MODEL, startVertex, endVertex);
+
+ osgUtil::IntersectionVisitor iv(picker.get());
+ iv.setTraversalMask(traversalMask);
+ nodePath.back()->accept(iv);
+
+ if (picker->containsIntersections())
+ {
+ intersections = picker->getIntersections();
+ return true;
+ }
+ else
+ {
+ intersections.clear();
+ return false;
+ }
+}
+#endif
+
+void ossimPlanetViewer::execute(const ossimPlanetAction& /*action*/)
+{
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetVisitors.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetVisitors.cpp
new file mode 100644
index 0000000..c56d6ed
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetVisitors.cpp
@@ -0,0 +1,112 @@
+#include <ossimPlanet/ossimPlanetVisitors.h>
+#include <ossimPlanet/ossimPlanetLayer.h>
+#include <ossimPlanet/ossimPlanetNode.h>
+
+void ossimPlanetLayerNameIdSearchVisitor::apply(osg::Node& node)
+{
+ ossimPlanetLayer* layer = dynamic_cast<ossimPlanetLayer*>(&node);
+ ossimPlanetNode* layerNode = dynamic_cast<ossimPlanetNode*>(&node);
+
+ if(theId.empty() && theName.empty()) return;
+
+ if(layer)
+ {
+ if(!theName.empty()&&!theId.empty())
+ {
+ if((layer->name() == theName)&&
+ (layer->id() == theId))
+ {
+ theNode = &node;
+ }
+ }
+ else if(!theName.empty())
+ {
+ if(layer->name() == theName)
+ {
+ theNode = &node;
+ }
+
+ }
+ else if(!theId.empty())
+ {
+ if(layer->id() == theId)
+ {
+ theNode = &node;
+ }
+ }
+ }
+ else if(layerNode)
+ {
+ if(!theName.empty()&&!theId.empty())
+ {
+ if((layerNode->name() == theName)&&
+ (layerNode->id() == theId))
+ {
+ theNode = &node;
+ }
+ }
+ else if(!theName.empty())
+ {
+ if(layerNode->name() == theName)
+ {
+ theNode = &node;
+ }
+
+ }
+ else if(!theId.empty())
+ {
+ if(layerNode->id() == theId)
+ {
+ theNode = &node;
+ }
+ }
+ }
+ if(theNode.valid()) return;
+ traverse(node);
+};
+
+ossimPlanetUpdateVisitor::ossimPlanetUpdateVisitor()
+:osgUtil::UpdateVisitor(),
+theRedrawFlag(false)
+{
+
+}
+
+void ossimPlanetUpdateVisitor::reset()
+{
+ theRedrawFlag = false;
+}
+
+bool ossimPlanetUpdateVisitor::redrawFlag()const
+{
+ return theRedrawFlag;
+}
+
+void ossimPlanetUpdateVisitor::apply(osg::Node& node)
+{
+ ossimPlanetNode* n = dynamic_cast<ossimPlanetNode*>(&node);
+ if(n)
+ {
+ if(n->redrawFlag())
+ {
+ n->setRedrawFlag(false);
+ theRedrawFlag = true;
+ }
+ }
+ UpdateVisitor::apply(node);
+}
+
+void ossimPlanetUpdateVisitor::apply(osg::Group& node)
+{
+ ossimPlanetNode* n = dynamic_cast<ossimPlanetNode*>(&node);
+ if(n)
+ {
+ if(n->redrawFlag())
+ {
+ n->setRedrawFlag(false);
+ theRedrawFlag = true;
+ }
+ }
+ UpdateVisitor::apply(node);
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetWmsClient.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetWmsClient.cpp
new file mode 100644
index 0000000..f766a13
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetWmsClient.cpp
@@ -0,0 +1,246 @@
+#ifndef OSGPLANET_WITHOUT_WMS
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <map>
+#include <ossimPlanet/ossimPlanetWmsClient.h>
+#include <ossimPlanet/ossimPlanetImage.h>
+#include <ossimPlanet/ossimPlanetJpegImage.h>
+#include <ossimPlanet/ossimPlanetOssimImage.h>
+#include <wms/wmsCurlMemoryStream.h>
+#include <wms/wmsMemoryStream.h>
+#include <wms/wmsClient.h>
+#include <ossim/imaging/ossimJpegTileSource.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/base/ossimIrect.h>
+#include <osgDB/ReadFile>
+#include <osgDB/Input>
+#include <osgDB/Registry>
+#include <ossimPlanet/ossimPlanetJpegImage.h>
+
+ossimPlanetWmsClient::ossimPlanetWmsClient(const std::string& server,
+ const std::string& path)
+ :osg::Referenced(),
+ theServer(server),
+ thePath(path),
+ theImageType("image/jpeg"),
+ theVersion("1.1.1")
+{
+ theWmsClient = new wmsClient;
+ theImageReader = new ossimPlanetOssimImage;
+}
+ossimPlanetWmsClient::ossimPlanetWmsClient(const ossimPlanetWmsClient& src)
+ :osg::Referenced(),
+ theServer(src.theServer),
+ thePath(src.thePath),
+ theImageFormats(src.theImageFormats),
+ theImageType(src.theImageType),
+ theVersion(src.theVersion),
+ theAdditionalParameters(src.theAdditionalParameters),
+ theBackgroundColor(src.theBackgroundColor),
+ theTransparentFlag(src.theTransparentFlag)
+{
+
+}
+
+ossimPlanetWmsClient::~ossimPlanetWmsClient()
+{
+}
+
+void ossimPlanetWmsClient::setServer(const std::string& server)
+{
+ theServer = server;
+}
+
+void ossimPlanetWmsClient::setPath(const std::string& path)
+{
+ thePath = path;
+}
+
+void ossimPlanetWmsClient::setAdditionalParameters(const ossimString& additionalParameters)
+{
+ theAdditionalParameters = additionalParameters.string();
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetWmsClient::createImage(ossim_uint32 width,
+ ossim_uint32 height,
+ const double& minLat,
+ const double& minLon,
+ const double& maxLat,
+ const double& maxLon,
+ const std::string& filename)
+{
+
+
+ osg::ref_ptr<ossimPlanetImage> planetImage = NULL;
+ ossimFilename file = filename.c_str();
+ wmsRefPtr<wmsMemoryStream> s;
+ bool needToRetrieve = true;
+
+ if(file!= "")
+ {
+ planetImage = readLocalImage(file);
+ if(planetImage.valid())
+ {
+ return planetImage;
+ }
+ }
+ if(needToRetrieve)
+ {
+ wmsUrl tempUrl = theWmsClient->getMapUrl(theServer,
+ width,
+ height,
+ minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ theImageType,
+ theVersion);
+// std::cout << "ossimPlanetWmsClient::createImage: Server = " << tempUrl << std::endl;
+
+ std::string tempStr = tempUrl.url();
+ if(theBackgroundColor != "")
+ {
+ tempStr += ("&BGCOLOR="+theBackgroundColor);
+ if(theTransparentFlag)
+ {
+ tempStr += ("&TRANSPARENT=TRUE");
+ }
+ else
+ {
+ tempStr += ("&TRANSPARENT=FALSE");
+ }
+ if(theAdditionalParameters != "")
+ {
+ tempStr += "&"+theAdditionalParameters;
+ }
+ }
+// std::cout << "ossimPlanetWmsClient::createImage: GETTING URL = " << tempStr << std::endl;
+ tempUrl = tempStr;
+ if(theWmsClient->get(tempUrl))
+ {
+ wmsRefPtr<wmsMemoryStream> memS = theWmsClient->getStream();
+ if(memS->getBufferSize()>0)
+ {
+ if(file!= "")
+ {
+ ofstream out(file.c_str(),
+ ios::out|ios::binary);
+ if(out.good())
+ {
+ out.write((char*)(memS->getBuffer()),
+ memS->getBufferSize());
+ out.close();
+ planetImage = new ossimPlanetImage;
+ ossimPlanetOssimImage inputImage;
+ if(!inputImage.loadFile(file, *planetImage))
+ {
+ planetImage = 0;
+ }
+ }
+ }
+ else
+ {
+ planetImage = new ossimPlanetImage;
+ if(planetImage.valid())
+ {
+ ossimPlanetJpegImage jpegImage;
+ if(!jpegImage.loadFile(*memS, *planetImage))
+ {
+ planetImage = 0;
+ }
+ }
+ else
+ {
+ std::cerr << "ERROR: ossimPlanetWmsClient::createImage allocating planetImage" << std::endl;
+ planetImage = 0;
+ }
+ }
+ }
+ else
+ {
+ std::cerr << "ERROR: ossimPlanetWmsClient::createImage allocating osgMemoryStream" << std::endl;
+ }
+ }
+ }
+
+ return planetImage;
+}
+
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetWmsClient::readLocalImage(const std::string& filename)const
+{
+ ossimFilename file = filename.c_str();
+ osg::ref_ptr<ossimPlanetImage> result;
+ if(file.exists())
+ {
+ result = new ossimPlanetImage;
+ bool readImage = false;
+// ossimPlanetJpegImage jpegImage;
+// if(jpegImage.loadFile(file, *result))
+// {
+// readImage = true;
+// }
+ if(!readImage)
+ {
+// ossimPlanetOssimImage inputImage;
+ if(!theImageReader->loadFile(file, *result))
+ {
+ result = 0;
+ }
+ }
+ }
+
+ return result;
+}
+
+void ossimPlanetWmsClient::setImageType(const std::string& imageType)
+{
+ if(imageType == "")
+ {
+ theImageType = "image/jpeg";
+ }
+ else
+ {
+ theImageType = imageType;
+ }
+}
+
+// void ossimPlanetWmsClient::setCacheDir(const std::string& cacheDir)
+// {
+// theCacheDir = cacheDir;
+// }
+
+std::string ossimPlanetWmsClient::getImageType()const
+{
+ return theImageType;
+}
+
+std::string ossimPlanetWmsClient::getServer()const
+{
+ return theServer;
+}
+
+std::string ossimPlanetWmsClient::getPath()const
+{
+ return thePath;
+}
+
+void ossimPlanetWmsClient::setTransparentFlag(bool flag)
+{
+ theTransparentFlag = flag;
+}
+
+void ossimPlanetWmsClient::setBackgroundColor(const std::string& color)
+{
+ theBackgroundColor = color;
+}
+
+
+// std::string ossimPlanetWmsClient::getCacheDir()const
+// {
+// return theCacheDir;
+// }
+
+#endif
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetWmsImageLayer.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetWmsImageLayer.cpp
new file mode 100644
index 0000000..2a4458a
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetWmsImageLayer.cpp
@@ -0,0 +1,922 @@
+#include <ossimPlanet/ossimPlanetWmsImageLayer.h>
+#include <sstream>
+#include <ossimPlanet/ossimPlanetWmsClient.h>
+#include <ossim/imaging/ossimMemoryImageSource.h>
+#include <ossim/imaging/ossimJpegWriter.h>
+#include <wms/wmsCapabilitiesParser.h>
+#include <wms/wmsCapabilitiesRoot.h>
+#include <wms/wmsCapabilitiesState.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+
+ossimPlanetWmsImageLayer::ossimPlanetWmsImageLayer()
+ :ossimPlanetTextureLayer(),
+ theAutoCreateCacheFlag(true)
+
+{
+ theImageType = "image/jpeg";
+
+ theTransparentColorFlag = true;
+ theBackgroundColor = "0x000000";
+ theTransparentFlag = false;
+ theWmsClient = new ossimPlanetWmsClient;
+}
+
+ossimPlanetWmsImageLayer::ossimPlanetWmsImageLayer(const ossimPlanetWmsImageLayer& src)
+ :ossimPlanetTextureLayer(src),
+ theImageType(src.theImageType),
+ theRawCapabilities(src.theRawCapabilities),
+ theCapabilitiesUrl(src.theCapabilitiesUrl),
+ theBackgroundColor(src.theBackgroundColor),
+ theTransparentFlag(src.theTransparentFlag),
+ theAdditionalParameters(src.theAdditionalParameters),
+ theProxyHost(src.theProxyHost),
+ theProxyPort(src.theProxyPort),
+ theProxyUser(src.theProxyUser),
+ theProxyPassword(src.theProxyPassword),
+ theAutoCreateCacheFlag(src.theAutoCreateCacheFlag)
+{
+ if(src.theWmsClient.valid())
+ {
+ theWmsClient = new ossimPlanetWmsClient(*(src.theWmsClient.get()));
+ theWmsClient->setProxyHost(theProxyHost);
+ theWmsClient->setProxyPort(theProxyPort);
+ theWmsClient->setProxyUser(theProxyUser);
+ theWmsClient->setProxyPassword(theProxyPassword);
+ }
+ else
+ {
+ theWmsClient = new ossimPlanetWmsClient;
+ }
+ theWmsClient->setProxyHost(theProxyHost);
+ theWmsClient->setProxyPort(theProxyPort);
+ theWmsClient->setProxyUser(theProxyUser);
+ theWmsClient->setProxyPassword(theProxyPassword);
+}
+
+ossimPlanetTextureLayer* ossimPlanetWmsImageLayer::dup()const
+{
+ return new ossimPlanetWmsImageLayer(*this);
+}
+
+ossimPlanetTextureLayer* ossimPlanetWmsImageLayer::dupType()const
+{
+ return new ossimPlanetWmsImageLayer;
+}
+
+ossimString ossimPlanetWmsImageLayer::getClassName()const
+{
+ return "ossimPlanetWmsImageLayer";
+}
+
+ossimPlanetTextureLayerStateCode ossimPlanetWmsImageLayer::updateExtents()
+{
+ theStateCode = ossimPlanetTextureLayer_VALID;
+ if(!theDirtyExtentsFlag) return theStateCode;
+
+ ossimString name = "LAYERS";
+ if(!theServer.contains(name))
+ {
+ name = "layers";
+ if(!theServer.contains(name))
+ {
+ return theStateCode;
+ }
+ }
+#if 1
+ bool extentsSet = false;
+ double minLat, maxLat, minLon, maxLon;
+ ossimString after = theServer.after(name);
+ after = after.after("=");
+ after = after.trim();
+ double maxScale = 0.0;
+ double minScale = 0.0;
+ if(after!= "")
+ {
+ wmsRefPtr<wmsCapabilitiesParser> parser = new wmsCapabilitiesParser;
+ std::stringstream in(theRawCapabilities);
+ wmsRefPtr<wmsCapabilitiesRoot> root = parser->parse(in);
+
+ if(root.valid())
+ {
+ after = after.before("&");
+ std::vector<ossimString> splitList;
+
+ after.split(splitList, ",");
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < splitList.size();++idx)
+ {
+ wmsRefPtr<wmsCapabilitiesState> node = root->getNodeGivenName(splitList[idx]);
+ if(node.valid())
+ {
+ node->getLatLonBoundingBox(minLat, minLon, maxLat, maxLon);
+ ossimString tempMaxScale = node->maxScaleHint();
+ ossimString tempMinScale = node->minScaleHint();
+ double scale = tempMaxScale.toDouble();
+
+ if(!tempMaxScale.empty())
+ {
+ if(scale > maxScale)
+ {
+ maxScale = scale;
+ }
+ }
+ if(!tempMinScale.empty())
+ {
+ minScale = tempMinScale.toDouble();
+ }
+ if(!extentsSet)
+ {
+ theExtents->setMinMaxLatLon(minLat, minLon, maxLat, maxLon);
+ extentsSet = true;
+ }
+ else
+ {
+ theExtents->combineMinMaxLatLon(minLat, minLon, maxLat, maxLon);
+ }
+ }
+ }
+ if(maxScale > 0.0)
+ {
+ theExtents->setMinMaxScale(minScale, maxScale);
+ }
+ }
+ }
+#endif
+ theDirtyExtentsFlag = false;
+
+ return theStateCode;
+}
+
+
+void ossimPlanetWmsImageLayer::updateStats()const
+{
+ theStats->setTotalTextureSize(0);
+}
+
+void ossimPlanetWmsImageLayer::resetStats()const
+{
+ updateStats();
+ theStats->setBytesTransferred(0);
+}
+
+bool ossimPlanetWmsImageLayer::hasTexture(ossim_uint32 /* width */,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid)
+{
+ ossimPlanetGrid::GridBound bound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ ossimPlanetGrid::GridBound tileBound;
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return false;
+ }
+ }
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ //double deltaLon = (deltaXY[0])/(double)(width);
+
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ ossimPlanetGrid::ModelPoint minLatLon, maxLatLon;
+ grid.modelBound(tileId, minLatLon, maxLatLon);
+ if(gsd.y <= theExtents->getMaxScale())
+ {
+ return true;
+ }
+// if((gsd.y >= theExtents->getMinScale()) &&
+// (gsd.y <= theExtents->getMaxScale()))
+// {
+// return true;
+// }
+
+ return false;
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetWmsImageLayer::getTexture(ossim_uint32 width,
+ ossim_uint32 height,
+ const ossimPlanetTerrainTileId& tileId,
+ const ossimPlanetGrid& grid,
+ ossim_int32 /*padding*/)
+{
+ if(!getEnableFlag())
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theWmsArchiveMutex);
+ if(theServer == "")
+ {
+ return 0;
+ }
+ ossimPlanetGrid::GridBound bound;
+ ossimPlanetGrid::GridBound tileBound;
+ if(grid.findGridBound(tileId.face(),
+ ossimPlanetGrid::ModelPoint(theExtents->getMinLon(), theExtents->getMinLat()),
+ ossimPlanetGrid::ModelPoint(theExtents->getMaxLon(), theExtents->getMaxLat()),
+ bound))
+ {
+ grid.bounds(tileId,tileBound);
+ if(!tileBound.toDrect().intersects(bound.toDrect()))
+ {
+ return 0;
+ }
+ }
+ osg::Vec2d deltaXY;
+ grid.widthHeightInModelSpace(tileId, deltaXY);
+ double deltaLat = (deltaXY[1])/(double)(height);
+ //double deltaLon = (deltaXY[0])/(double)(width);
+ //std::cout << "Delta lat = "<<deltaLat << std::endl;
+ //std::cout << "Delta lon = "<<deltaLon << std::endl;
+
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+ ossimPlanetGrid::ModelPoint minLatLon, maxLatLon;
+ grid.modelBound(tileId, minLatLon, maxLatLon);
+
+ if(gsd.y > theExtents->getMaxScale())//!//theExtents->intersectsScale(gsd.y-FLT_EPSILON,
+ // gsd.y+FLT_EPSILON))//gsd.y <= theExtents.theMaxGsd)
+ {
+ return 0;
+ }
+ //std::cout << "Model bound = " << minLatLon << " , " << maxLatLon << std::endl;
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+ std::stringstream file;
+ ossimFilename filename;
+ // ossimPlanetWmsClient client(theAdjustedServer);
+ // client.setImageType(theImageType);
+
+ // bool hasCacheDir = false;
+ if((theCompleteCacheDirectory!="")&&
+ (!theCompleteCacheDirectory.exists())&&
+ (theAutoCreateCacheFlag))
+ {
+ theCompleteCacheDirectory.createDirectory();
+ }
+ if((theCompleteCacheDirectory != "")&&
+ theCompleteCacheDirectory.exists())
+ {
+ filename = theCompleteCacheDirectory;
+ file << "F" << tileId.face() << "_L" <<tileId.level() <<"_X"<<tileId.x()<<"_Y"<<tileId.y();
+ filename = filename.dirCat(file.str().c_str());
+ if(filename.exists())
+ {
+ texture = theWmsClient->readLocalImage(filename);
+ }
+ // hasCacheDir = true;
+ }
+ if(!texture.valid())
+ {
+ if(!grid.isPolar(tileId))
+ {
+ ossimFilename tempFile;
+ if(!filename.empty())
+ {
+ tempFile = filename+"_tmp";
+ }
+ texture = theWmsClient->createImage(width,
+ height,
+ minLatLon.y(),
+ minLatLon.x(),
+ maxLatLon.y(),
+ maxLatLon.x(),
+ tempFile);
+ if(texture.valid())
+ {
+ if(tempFile.exists())
+ {
+ tempFile.rename(filename);
+ }
+ }
+ }
+ }
+ if(texture.valid())
+ {
+ texture->flipVertical();
+ }
+
+ return texture.get();
+}
+
+osg::ref_ptr<ossimPlanetImage> ossimPlanetWmsImageLayer::getTexture(ossim_uint32 level,
+ ossim_uint64 row,
+ ossim_uint64 col,
+ const ossimPlanetGridUtility& utility)
+{
+ if(!getEnableFlag())
+ {
+ return 0;
+ }
+ if(theDirtyExtentsFlag)
+ {
+ updateExtents();
+ }
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theWmsArchiveMutex);
+ osg::ref_ptr<ossimPlanetImage> image = 0;
+
+ if(theServer == "")
+ {
+ return NULL;
+ }
+ double minLat;
+ double minLon;
+ double maxLat;
+ double maxLon;
+ ossim_uint32 w = utility.getTileWidth();
+ ossim_uint32 h = utility.getTileHeight();
+
+ utility.getLatLonBounds(minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ level,
+ row,
+ col);
+ if(!theExtents->intersectsLatLon(minLat, minLon, maxLat, maxLon))
+ {
+ return 0;
+ }
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ double deltaLat = deltaY/h;
+// double deltaLon = deltaX/w;
+ ossimDpt gsd = ossimGpt().metersPerDegree();
+ gsd.y *= deltaLat;
+
+ osg::ref_ptr<ossimPlanetImage> texture = 0;
+
+ if(gsd.y > theExtents->getMaxScale())//!//theExtents->intersectsScale(gsd.y-FLT_EPSILON,
+ // gsd.y+FLT_EPSILON))//gsd.y <= theExtents.theMaxGsd)
+ {
+ return 0;
+ }
+ std::stringstream file;
+ ossimFilename filename;
+// ossimPlanetWmsClient client(theAdjustedServer);
+// client.setImageType(theImageType);
+
+ // bool hasCacheDir = false;
+ if((theCompleteCacheDirectory!="")&&
+ (!theCompleteCacheDirectory.exists())&&
+ (theAutoCreateCacheFlag))
+ {
+ theCompleteCacheDirectory.createDirectory();
+ }
+ if((theCompleteCacheDirectory != "")&&
+ theCompleteCacheDirectory.exists())
+ {
+ filename = theCompleteCacheDirectory;
+ file << "L" <<level <<"_X"<<col<<"_Y"<<row;
+ filename = filename.dirCat(file.str().c_str());
+ // hasCacheDir = true;
+ }
+ if(!image.valid())
+ {
+ if(filename.exists())
+ {
+ filename.remove();
+ }
+ if(utility.getFace(level, row, col)<4)
+ {
+ ossimFilename tempFile;
+ if(!filename.empty())
+ {
+ tempFile = filename+"_tmp";
+ }
+ image = theWmsClient->createImage(w,
+ h,
+ minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ tempFile);
+ if(image.valid())
+ {
+ if(tempFile.exists())
+ {
+ tempFile.rename(filename);
+ }
+ }
+ }
+ else
+ {
+ double deltaX;
+ double deltaY;
+ utility.getWidthHeightInDegrees(deltaX, deltaY, level, row, col);
+
+ std::vector<ossimPlanetGridUtility::GridPoint> points;
+ utility.createGridPoints(points,
+ level,
+ row,
+ col,
+ w,
+ h);
+ std::vector<osg::Vec2d> minMaxPairs;
+ utility.getGeographicLonCrossings(minMaxPairs, level, row, col);
+
+ ossim_uint32 size = minMaxPairs.size();
+ ossim_uint32 idx = 0;
+
+ for(idx = 0; idx < size; ++idx)
+ {
+ ossimFilename tempFile;
+ if(filename != "")
+ {
+ tempFile = ossimFilename(filename + "_" + ossimString::toString(idx));
+ }
+ minLon = minMaxPairs[idx][0];
+ maxLon = minMaxPairs[idx][1];
+
+ double deltaLat = deltaY/h;
+ double deltaLon = deltaX/w;
+ //ossim_uint32 dx = (ossim_uint32)(((maxLon-minLon)/deltaLon));
+ //ossim_uint32 dy = (ossim_uint32)(((maxLat-minLat)/deltaLat));
+ ossimRefPtr<ossimImageData> data;
+ osg::ref_ptr<ossimPlanetImage> dataPlanetImage;
+
+ // need to fix this. This is actually wrong for the polare faces to do it like this. Note,
+ // the only WMS output projection that can do the world is geographic (that I know of), We really
+ // need a polar projectino server that is comon amond all WMS's or can be queried for support.
+ // For now I will leave it. But later I need to ad looping over all geographc tiles as yoou approach the
+ // pole. This would force a slow hit.
+ dataPlanetImage = theWmsClient->createImage(w,//dx,
+ h,//dy,
+ minLat,
+ minLon,
+ maxLat,
+ maxLon,
+ tempFile);
+ if((tempFile!= "")&&tempFile.exists())
+ {
+ tempFile.remove();
+ }
+ if(dataPlanetImage.valid())
+ {
+ data = dataPlanetImage->toOssimImage();
+ }
+ else
+ {
+ data = 0;
+ }
+ if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus()!=OSSIM_EMPTY))
+ {
+ if(!image.valid())
+ {
+ image = new ossimPlanetImage(ossimPlanetTerrainTileId(0,
+ level,
+ row,
+ col));
+ }
+ convertToOsg(data.get(),
+ image.get(),
+ osg::Vec2d(minLon,
+ maxLat),
+ osg::Vec2d(maxLon+deltaLon,
+ maxLat),
+ osg::Vec2d(maxLon+deltaLon,
+ minLat-deltaLat),
+ osg::Vec2d(minLon,
+ minLat-deltaLat),
+ points,
+ utility,
+ w,
+ h);
+
+ }
+ }
+ if(image.valid())
+ {
+ if(filename != "")
+ {
+ ossimPushNotifyFlags();
+ ossimSetNotifyFlag(ossimNotifyFlags_NONE);
+ ossimRefPtr<ossimImageData> data = image->toOssimImage();
+ ossimRefPtr<ossimMemoryImageSource> memSource = new ossimMemoryImageSource;
+
+ memSource->setImage(data.get());
+ theWriter->disconnect();
+ theWriter->connectMyInputTo(0, memSource.get());
+ theWriter->setOutputName(filename.c_str());
+ theWriter->execute();
+ ossimPopNotifyFlags();
+ }
+ }
+ }
+ if(image.valid())
+ {
+ image->setState(ossimPlanetImage::ossimPlanetImageStateType_LOADED);
+ }
+ }
+ else
+ {
+ image->setState(ossimPlanetImage::ossimPlanetImageStateType_LOADED);
+ }
+ if(image.valid())
+ {
+ image->setId(ossimPlanetTerrainTileId(0, level, col, row));
+ if(image->getNumberOfComponents() == 3)
+ {
+ insertAlpha(image.get());
+ }
+ if(theTransparentColorFlag)
+ {
+ addTransparent(image.get());
+ }
+ image->setPixelStatus();
+ if(utility.getFace(level, row, col)<4)
+ {
+ image->flipVertical();
+ }
+ }
+
+ return image;
+}
+
+void ossimPlanetWmsImageLayer::setServer(const std::string& serverString)
+{
+ theServer = serverString;
+
+ adjustServerString();
+
+ dirtyExtents();
+}
+
+const std::string& ossimPlanetWmsImageLayer::getServer()const
+{
+ return theServer;
+}
+
+void ossimPlanetWmsImageLayer::adjustServerString()
+{
+// std::cout << "SERVER STRING START = " << theServer << std::endl;
+ theAdjustedServer = theServer;
+ ossimString name = "FORMAT";
+ if(!theAdjustedServer.contains(name))
+ {
+ name = "format";
+ }
+ ossimString::size_type startPos = theAdjustedServer.find(name.string());
+ if(startPos!=std::string::npos)//theServer.contains(name))
+ {
+ ossimString formatString = theAdjustedServer.after(name.string());
+ formatString = formatString.after("=");
+ formatString = formatString.trim();
+ if(formatString!="")
+ {
+ theImageType = formatString.before("&");
+ }
+ ossimString::size_type endPos = theAdjustedServer.find("&", startPos);//+name.length());
+
+
+ if(endPos != std::string::npos)
+ {
+ endPos += 1;
+ theAdjustedServer.erase(theAdjustedServer.begin()+startPos, theAdjustedServer.begin()+endPos);
+ }
+ else
+ {
+ theAdjustedServer.erase(theAdjustedServer.begin()+startPos, theAdjustedServer.end());
+ }
+ }
+
+// std::cout << "ADJUSTED 1: " << theAdjustedServer << std::endl;
+ // now just extract layers and styles so we can determine directory cache
+ //
+ name = "LAYERS";
+ if(!theAdjustedServer.contains(name))
+ {
+ name = "layers";
+ }
+ startPos = theAdjustedServer.find(name.string());
+ if(startPos!=std::string::npos)
+ {
+ ossimString value = theAdjustedServer.after(name.string());
+ value = value.after("=");
+ value = value.trim();
+ if(value!="")
+ {
+ value = value.before("&");
+ }
+ ossimString::size_type endPos = theAdjustedServer.find("&", startPos);//+name.length());
+ if(endPos != std::string::npos)
+ {
+ endPos += 1;
+ }
+ value.split(theLayers, ",");
+ }
+ // now just extract layers and styles so we can determine directory cache
+ //
+ name = "STYLES";
+ if(!theAdjustedServer.contains(name))
+ {
+ name = "styles";
+ }
+ startPos = theAdjustedServer.find(name.string());
+ if(startPos!=std::string::npos)
+ {
+ ossimString value = theAdjustedServer.after(name.string());
+ value = value.after("=");
+ value = value.trim();
+ if(value!="")
+ {
+ value = value.before("&");
+ }
+ ossimString::size_type endPos = theAdjustedServer.find("&", startPos);//+name.length());
+ if(endPos != std::string::npos)
+ {
+ endPos += 1;
+ }
+ value.split(theStyles, ",");
+ }
+
+ // make sure we reset the full path directory by forcing a call
+ // to set cache directory
+ setCacheDirectory(getCacheDirectory());
+
+ theImageType = theImageType.downcase();
+ theWriter = 0;
+ // let's use our plugin writer if it exists. Seems to core dump on windows when using the GDAL png.
+// if(theImageType.downcase() == "image/png")
+// {
+// theWriter = ossimImageWriterFactoryRegistry::instance()->createWriter(ossimString("ossimPngWriter"));
+// }
+ if(!theWriter.valid())
+ {
+ theWriter = ossimImageWriterFactoryRegistry::instance()->createWriter(theImageType);
+ }
+ if(!theWriter.valid())
+ {
+ theWriter = new ossimJpegWriter;
+ }
+
+ if(!theAdjustedServer.empty())
+ {
+ if(!theAdjustedServer.contains("SRS=")&&
+ !theAdjustedServer.contains("srs="))
+ {
+ if(*(theAdjustedServer.begin() + theAdjustedServer.size()-1) != '&')
+ {
+ theAdjustedServer += "&";
+ }
+ theAdjustedServer += "SRS=EPSG:4326";
+ }
+ if(!theAdjustedServer.contains("SERVICE=")&&
+ !theAdjustedServer.contains("service="))
+ {
+ if(*(theAdjustedServer.begin() + theAdjustedServer.size()-1) != '&')
+ {
+ theAdjustedServer += "&";
+ }
+ theAdjustedServer += "SERVICE=WMS";
+
+ }
+ }
+ theWmsClient->setServer(theAdjustedServer);
+ theWmsClient->setImageType(theImageType);
+}
+
+const std::string& ossimPlanetWmsImageLayer::getImageType()const
+{
+ return theImageType;
+}
+
+void ossimPlanetWmsImageLayer::setImageType(const std::string& imageType)
+{
+ theImageType = imageType;
+}
+
+const ossimFilename& ossimPlanetWmsImageLayer::getCacheDirectory()const
+{
+ return theCacheDirectory;
+}
+
+const ossimFilename& ossimPlanetWmsImageLayer::getCompleteCacheDirectory()const
+{
+ return theCompleteCacheDirectory;
+}
+
+void ossimPlanetWmsImageLayer::setCacheDirectory(const ossimFilename& cacheDir)
+{
+ theCacheDirectory = cacheDir;
+ theCompleteCacheDirectory=cacheDir;
+ if(!theCacheDirectory.empty())
+ {
+ wmsUrl url(theAdjustedServer.string());
+ ossimString server = ossimFilename(ossimString(url.server()).substitute(".", "_", true));
+ server = server.substitute("/","_",true);
+ server = server.substitute(":","_",true);
+
+ if(!server.empty())
+ {
+ theCompleteCacheDirectory = theCacheDirectory.dirCat(server);
+ if(theLayers.size() == 1)// if it's not a composite
+ {
+ theCompleteCacheDirectory = theCacheDirectory.dirCat(server);
+ theCompleteCacheDirectory = theCompleteCacheDirectory.dirCat(theLayers[0]);
+ if(theStyles.size()==1)
+ {
+ theCompleteCacheDirectory = theCompleteCacheDirectory.dirCat(theStyles[0]);
+ }
+ }
+ }
+ if(!theCompleteCacheDirectory.exists())
+ {
+ theCompleteCacheDirectory.createDirectory(true);
+ }
+ }
+}
+
+void ossimPlanetWmsImageLayer::setRawCapabilities(const ossimString& rawCapabilities)
+{
+ theRawCapabilities = rawCapabilities;
+ dirtyExtents();
+}
+
+const ossimString& ossimPlanetWmsImageLayer::getRawCapabilities()const
+{
+ return theRawCapabilities;
+}
+
+void ossimPlanetWmsImageLayer::setCapabilitiesUrl(const std::string& url)
+{
+ theCapabilitiesUrl = url;
+ dirtyExtents();
+
+}
+
+const std::string& ossimPlanetWmsImageLayer::getCapabilitiesUrl()const
+{
+ return theCapabilitiesUrl;
+}
+
+void ossimPlanetWmsImageLayer::setBackgroundColor(const ossimString& color)
+{
+ theBackgroundColor = color;
+}
+
+const ossimString& ossimPlanetWmsImageLayer::getBackgroundColor()const
+{
+ return theBackgroundColor;
+}
+
+void ossimPlanetWmsImageLayer::setTransparentFlag(bool flag)
+{
+ theTransparentFlag = flag;
+}
+
+bool ossimPlanetWmsImageLayer::getTransparentFlag()const
+{
+ return theTransparentFlag;
+}
+
+void ossimPlanetWmsImageLayer::setAdditionalParameters(const ossimString& additionalParameters)
+{
+ theAdditionalParameters = additionalParameters;
+ dirtyExtents();
+}
+
+const ossimString& ossimPlanetWmsImageLayer::getAdditionalParameters()const
+{
+ return theAdditionalParameters;
+}
+
+void ossimPlanetWmsImageLayer::setAutoCreateCacheFlag(bool value)
+{
+ theAutoCreateCacheFlag = value;
+}
+
+bool ossimPlanetWmsImageLayer::getAutoCreateCacheFlag()const
+{
+ return theAutoCreateCacheFlag;
+}
+
+void ossimPlanetWmsImageLayer::clearDiskCache()
+{
+ if(theCompleteCacheDirectory.exists())
+ {
+ ossimFilename wildcardFiles = theCompleteCacheDirectory.dirCat(".*");
+ ossimFilename::wildcardRemove(wildcardFiles);
+ }
+}
+
+ossimRefPtr<ossimXmlNode> ossimPlanetWmsImageLayer::saveXml(bool /*recurse*/)const
+{
+ ossimRefPtr<ossimXmlNode> result = ossimPlanetTextureLayer::saveXml();
+
+ result->addChildNode("cacheDirectory", theCacheDirectory);
+ result->addChildNode("completeCacheDirectory", theCompleteCacheDirectory);
+ result->addChildNode("server", theServer);
+ result->addChildNode("imageType", theImageType);
+ result->addChildNode("capabilitiesUrl", theCapabilitiesUrl);
+ result->addChildNode("backgroundColor", theBackgroundColor);
+ result->addChildNode("transparentColorFlag", ossimString::toString(theTransparentFlag));
+ result->addChildNode("additionalParameters", theAdditionalParameters);
+
+ result->addChildNode("proxyHost", theProxyHost);
+ result->addChildNode("proxyPort", theProxyPort);
+ result->addChildNode("proxyUser", theProxyUser);
+ result->addChildNode("proxyPassword", theProxyPassword);
+
+ return result.get();
+}
+
+bool ossimPlanetWmsImageLayer::loadXml(ossimRefPtr<ossimXmlNode> node)
+{
+ if(!ossimPlanetTextureLayer::loadXml(node)) return false;
+
+ ossimRefPtr<ossimXmlNode> server = node->findFirstNode("server");
+ ossimRefPtr<ossimXmlNode> imageType = node->findFirstNode("imageType");
+ ossimRefPtr<ossimXmlNode> cacheDirectory = node->findFirstNode("cacheDirectory");
+ ossimRefPtr<ossimXmlNode> capabilitiesUrl = node->findFirstNode("capabilitiesUrl");
+ ossimRefPtr<ossimXmlNode> backgroundColor = node->findFirstNode("backgroundColor");
+ ossimRefPtr<ossimXmlNode> transparentFlag = node->findFirstNode("transparentFlag");
+ ossimRefPtr<ossimXmlNode> additionalParameters = node->findFirstNode("additionalParameters");
+ ossimRefPtr<ossimXmlNode> extents = node->findFirstNode("ossimPlanetExtents");
+ ossimRefPtr<ossimXmlNode> lookAt = node->findFirstNode("ossimPlanetLookAt");
+ ossimRefPtr<ossimXmlNode> proxyHost = node->findFirstNode("proxyHost");
+ ossimRefPtr<ossimXmlNode> proxyPort = node->findFirstNode("proxyPort");
+ ossimRefPtr<ossimXmlNode> proxyUser = node->findFirstNode("proxyUser");
+ ossimRefPtr<ossimXmlNode> proxyPassword = node->findFirstNode("proxyPassword");
+
+ if(!transparentFlag.valid())
+ {
+ transparentFlag = node->findFirstNode("transparentColorFlag");
+ }
+ if(server.valid())
+ {
+ setServer(server->getText());
+ }
+ if(imageType.valid())
+ {
+ setImageType(imageType->getText());
+ }
+ if(cacheDirectory.valid())
+ {
+ setCacheDirectory(cacheDirectory->getText());
+ }
+ if(capabilitiesUrl.valid())
+ {
+ setCapabilitiesUrl(capabilitiesUrl->getText());
+ }
+ if(backgroundColor.valid())
+ {
+ setBackgroundColor(backgroundColor->getText());
+ }
+ if(transparentFlag.valid())
+ {
+ setTransparentFlag(transparentFlag->getText().toBool());
+ }
+ if(additionalParameters.valid())
+ {
+ setAdditionalParameters(additionalParameters->getText());
+ }
+ if(extents.valid())
+ {
+ getExtents()->loadXml(extents.get());
+ }
+ if(proxyHost.valid())
+ {
+ setProxyHost(proxyHost->getText());
+ }
+ else
+ {
+ setProxyHost("");
+ }
+ if(proxyPort.valid())
+ {
+ setProxyPort(proxyPort->getText());
+ }
+ else
+ {
+ setProxyPort("");
+ }
+ if(proxyUser.valid())
+ {
+ setProxyUser(proxyUser->getText());
+ }
+ else
+ {
+ setProxyUser("");
+ }
+ if(proxyPassword.valid())
+ {
+ setProxyPassword(proxyPassword->getText());
+ }
+ else
+ {
+ setProxyPassword("");
+ }
+ return server.valid();
+}
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetXmlAction.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetXmlAction.cpp
new file mode 100644
index 0000000..f1dc094
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetXmlAction.cpp
@@ -0,0 +1,225 @@
+#include <ossimPlanet/ossimPlanetXmlAction.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <sstream>
+
+ossimPlanetXmlAction::ossimPlanetXmlAction(const ossimString& code,
+ const ossimString& originatingFederate)
+:ossimPlanetAction(originatingFederate)
+{
+ setSourceCode(code);
+}
+
+ossimPlanetXmlAction::ossimPlanetXmlAction(ossimRefPtr<ossimXmlNode> code,
+ const ossimString& originatingFederate)
+:ossimPlanetAction(originatingFederate)
+{
+ setXmlNode(code);
+}
+
+void ossimPlanetXmlAction::setTarget(const ossimString& value)
+{
+ ossimPlanetAction::setTarget(value);
+ if(theXmlNode.valid())
+ {
+ if(theXmlNode->getAttributeValue("target") != value.c_str())
+ {
+ // add the attribute if not present already else change it
+ //
+ theXmlNode->setAttribute("target", value, true);
+ std::ostringstream out;
+ out << *theXmlNode;
+ theSourceCode = out.str();
+ }
+ }
+}
+
+void ossimPlanetXmlAction::setCommand(const ossimString& value)
+{
+ ossimPlanetAction::setCommand(value);
+
+ // Update the tag value if the command changes.
+ if(theXmlNode.valid() &&(theXmlNode->getTag()!=value.c_str()))
+ {
+ theXmlNode->setTag(value);
+ std::ostringstream out;
+ out << *theXmlNode;
+ theSourceCode = out.str();
+ }
+}
+
+bool ossimPlanetXmlAction::setSourceCode(const ossimString& code)
+{
+ ossim_uint32 bytesRead = 0;
+ ossimRefPtr<ossimXmlNode> node = 0;
+ if(code[(size_t)0] == '<')
+ {
+ std::istringstream in(code);
+ if(code[(size_t)1] == '?')
+ {
+ ossimRefPtr<ossimXmlDocument> doc = new ossimXmlDocument;
+ if(doc->read(in))
+ {
+ node = doc->getRoot();
+ }
+ }
+ else
+ {
+ node = new ossimXmlNode;
+ if(!node->read(in))
+ {
+ node = 0;
+ }
+ }
+ bytesRead = in.tellg();
+ }
+ // now setup the sourcecode that was read in
+ //
+ if(bytesRead > 0)
+ {
+ theSourceCode = ossimString(code.begin(),
+ code.begin() + bytesRead);
+ }
+
+ setXmlNode(node.get());
+ return node.valid();
+}
+
+void ossimPlanetXmlAction::setXmlNode(ossimRefPtr<ossimXmlNode> node)
+{
+ theXmlNode = node;
+ if(theXmlNode.valid())
+ {
+ ossimString value;
+ setCommand(theXmlNode->getTag());
+ if(theXmlNode->getAttributeValue(value, "target"))
+ {
+ setTarget(value);
+ }
+ else
+ {
+ setTarget("");
+ }
+ if(theXmlNode->getAttributeValue(value, "origin"))
+ {
+ setOrigin(value);
+ }
+ else
+ {
+ setOrigin("");
+ }
+ std::ostringstream out;
+ out << *theXmlNode;
+ theSourceCode = out.str();
+ }
+ else
+ {
+ setTarget("");
+ setOrigin("");
+ theSourceCode = "";
+ }
+}
+
+ossimString ossimPlanetXmlAction::id()const
+{
+ if(theXmlNode.valid())
+ {
+ return theXmlNode->getAttributeValue("id");
+ }
+
+ return "";
+}
+
+ossimString ossimPlanetXmlAction::name()const
+{
+ if(theXmlNode.valid())
+ {
+ return theXmlNode->getAttributeValue("name");
+ }
+
+ return "";
+}
+
+osg::ref_ptr<ossimPlanetXmlAction> ossimPlanetXmlAction::duplicateChildAndMaintainAction(ossim_uint32 childIdx)const
+{
+ osg::ref_ptr<ossimPlanetXmlAction> result;
+ if(theXmlNode.valid())
+ {
+ const ossimXmlNode::ChildListType& children = theXmlNode->getChildNodes();
+ if(childIdx < children.size())
+ {
+ ossimXmlNode::AttributeListType attributes;
+ theXmlNode->duplicateAttributes(attributes);
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ node->setAttributes(attributes);
+ node->addChildNode((ossimXmlNode*)children[childIdx]->dup());
+ node->setTag(theXmlNode->getTag());
+ result = new ossimPlanetXmlAction(node, origin());
+ result->setTarget(target());
+ }
+ }
+
+ return result;
+}
+
+osg::ref_ptr<ossimPlanetXmlAction> ossimPlanetXmlAction::duplicateChildPropertiesAndMaintainAction(ossim_uint32 childIdx)const
+{
+ osg::ref_ptr<ossimPlanetXmlAction> result;
+ if(theXmlNode.valid())
+ {
+ const ossimXmlNode::ChildListType& children = theXmlNode->getChildNodes();
+
+ if(childIdx < children.size())
+ {
+ ossimString value;
+ ossimXmlNode::ChildListType dupChildren;
+ ossimXmlNode::AttributeListType attributes;
+ theXmlNode->duplicateAttributes(attributes);
+ ossimRefPtr<ossimXmlNode> propertyNode = new ossimXmlNode;
+ children[childIdx]->duplicateChildren(dupChildren);
+ propertyNode->setAttributes(attributes);
+ propertyNode->setChildren(dupChildren);
+ propertyNode->setTag(command());
+
+ result = new ossimPlanetXmlAction(propertyNode,
+ origin());
+ }
+ }
+
+ return result;
+}
+
+bool ossimPlanetXmlAction::hasChildren()const
+{
+ bool result = false;
+
+ if(theXmlNode.valid())
+ {
+ return theXmlNode->getChildNodes().size();
+ }
+
+ return false;
+}
+
+void ossimPlanetXmlAction::print(std::ostream& out)const
+{
+ if(theXmlNode.valid())
+ {
+ out << *theXmlNode;
+ }
+}
+
+void ossimPlanetXmlAction::read(std::istream& in)
+{
+ ossimRefPtr<ossimXmlNode> node = new ossimXmlNode;
+ if(node->read(in))
+ {
+ setXmlNode(theXmlNode.get());
+ }
+ else
+ {
+ setTarget(":");
+ setCommand("#syntaxerror");
+ }
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ossimPlanetYahooGeocoder.cpp b/ossimPlanet/src/ossimPlanet/ossimPlanetYahooGeocoder.cpp
new file mode 100644
index 0000000..f754507
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ossimPlanetYahooGeocoder.cpp
@@ -0,0 +1,87 @@
+#include <ossimPlanet/ossimPlanetYahooGeocoder.h>
+#include <wms/wmsCurlMemoryStream.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <sstream>
+
+void ossimPlanetYahooGeocoder::getLocationFromAddress(std::vector<osg::ref_ptr<ossimPlanetGeocoderLocation> >& result,
+ const ossimString& location)const
+{
+ ossimString url = theUrl + "appid=" + theAppId +"&location="+location.substitute(" ", "+", true);
+ wmsCurlMemoryStream curl(url);
+
+ if(curl.download())
+ {
+ ossimXmlDocument xml;
+ ossimString buffer = curl.getStream()->getBufferAsString();
+ std::istringstream in(buffer);
+ if(xml.read(in))
+ {
+ std::vector<ossimRefPtr<ossimXmlNode> > nodes;
+ xml.findNodes("/ResultSet/Result",
+ nodes);
+ if(nodes.size())
+ {
+ osg::ref_ptr<ossimPlanetGeocoderLocation> location = new ossimPlanetGeocoderLocation;
+ ossim_uint32 idx = 0;
+ for(idx = 0; idx < nodes.size(); ++idx)
+ {
+ ossimRefPtr<ossimXmlNode> lat = nodes[idx]->findFirstNode("Latitude");
+ ossimRefPtr<ossimXmlNode> lon = nodes[idx]->findFirstNode("Longitude");
+ ossimRefPtr<ossimXmlNode> zip = nodes[idx]->findFirstNode("Zip");
+ ossimRefPtr<ossimXmlNode> city = nodes[idx]->findFirstNode("City");
+ ossimRefPtr<ossimXmlNode> state = nodes[idx]->findFirstNode("State");
+ ossimRefPtr<ossimXmlNode> address = nodes[idx]->findFirstNode("Address");
+ ossimRefPtr<ossimXmlNode> country = nodes[idx]->findFirstNode("Country");
+ if(lat.valid()&&lon.valid())
+ {
+ ossimGpt gpt(lat->getText().toDouble(),
+ lon->getText().toDouble());
+ location->setLocation(gpt);
+ ossimString name;
+
+ if(address.valid())
+ {
+ name = address->getText().trim();
+ }
+ if(city.valid())
+ {
+ if(!name.empty())
+ {
+ name += ", ";
+ }
+ name += city->getText().trim();
+ }
+ if(state.valid())
+ {
+ if(!name.empty())
+ {
+ name += ", ";
+ }
+ name += state->getText().trim();
+ }
+ if(zip.valid())
+ {
+ if(!name.empty())
+ {
+ name += ", ";
+ }
+ name += zip->getText().trim();
+ }
+ if(country.valid())
+ {
+ if(!name.empty())
+ {
+ name += ", ";
+ }
+ name += country->getText().trim();
+ }
+ location->setName(name);
+
+ result.push_back(location);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ossimPlanet/src/ossimPlanet/sg_file.cpp b/ossimPlanet/src/ossimPlanet/sg_file.cpp
new file mode 100644
index 0000000..eff249e
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/sg_file.cpp
@@ -0,0 +1,143 @@
+// sg_file.cxx -- File I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: sg_file.cpp 10536 2007-02-27 14:59:55Z gpotts $
+
+
+#include <ossimPlanet/compiler.h>
+#include <ossim/base/ossimNotify.h>
+#include STL_STRING
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+# include <io.h>
+#endif
+
+#include <ossimPlanet/sg_file.h>
+#include <string.h> // for strlen
+
+SG_USING_STD(string);
+
+
+SGFile::SGFile( const string &file) {
+ set_type( sgFileType );
+ file_name = file;
+ eof_flag = true;
+}
+
+
+SGFile::~SGFile() {
+}
+
+
+// open the file based on specified direction
+bool SGFile::open( const SGProtocolDir d ) {
+ set_dir( d );
+
+ if ( get_dir() == SG_IO_OUT ) {
+#if defined(_MSC_VER) || defined(__MINGW32__)
+ int mode = 00666;
+#else
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+#endif
+ fp = ::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode );
+ } else if ( get_dir() == SG_IO_IN ) {
+ fp = ::open( file_name.c_str(), O_RDONLY );
+ } else {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: bidirection mode not available for files." );
+ return false;
+ }
+
+ if ( fp == -1 ) {
+// SG_LOG( SG_IO, SG_ALERT, "Error opening file: " << file_name );
+ return false;
+ }
+
+ eof_flag = false;
+ return true;
+}
+
+
+// read a block of data of specified size
+int SGFile::read( char *buf, int length ) {
+ // read a chunk
+ size_t result = ::read( fp, buf, length );
+ if ( length > 0 && result == 0 ) {
+ eof_flag = true;
+ }
+ return result;
+}
+
+
+// read a line of data, length is max size of input buffer
+int SGFile::readline( char *buf, int length ) {
+ // save our current position
+ int pos = lseek( fp, 0, SEEK_CUR );
+
+ // read a chunk
+ size_t result = ::read( fp, buf, length );
+ if ( length > 0 && result == 0 ) {
+ eof_flag = true;
+ }
+
+ // find the end of line and reset position
+ int i;
+ for ( i = 0; i < result && buf[i] != '\n'; ++i );
+ if ( buf[i] == '\n' ) {
+ result = i + 1;
+ } else {
+ result = i;
+ }
+ lseek( fp, pos + result, SEEK_SET );
+
+ // just in case ...
+ buf[ result ] = '\0';
+
+ return result;
+}
+
+
+// write data to a file
+int SGFile::write( const char *buf, const int length ) {
+ int result = ::write( fp, buf, length );
+ if ( result != length ) {
+ ossimNotify(ossimNotifyLevel_WARN) << "Error writing data: " << file_name << std::endl;
+ }
+
+ return result;
+}
+
+
+// write null terminated string to a file
+int SGFile::writestring( const char *str ) {
+ int length = strlen( str );
+ return write( str, length );
+}
+
+
+// close the port
+bool SGFile::close() {
+ if ( ::close( fp ) == -1 ) {
+ return false;
+ }
+
+ eof_flag = true;
+ return true;
+}
diff --git a/ossimPlanet/src/ossimPlanet/sg_socket.cpp b/ossimPlanet/src/ossimPlanet/sg_socket.cpp
new file mode 100644
index 0000000..53da340
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/sg_socket.cpp
@@ -0,0 +1,494 @@
+// sg_socket.cxx -- Socket I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+// Modified by Bernie Bright <bbright at bigpond.net.au>, May 2002.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: sg_socket.cpp 11616 2007-08-15 18:23:33Z gpotts $
+
+#include <ossimPlanet/compiler.h>
+#include <ossim/base/ossimString.h>
+#if defined( sgi )
+#include <strings.h>
+#endif
+
+#include STL_IOSTREAM
+
+
+#include <ossimPlanet/sg_socket.h>
+
+bool SGSocket::init = false;
+
+SGSocket::SGSocket( const string& host, const string& port_,
+ const string& style )
+ :SGIOChannel(),
+ hostname(host),
+ port_str(port_),
+ save_len(0),
+ client(0),
+ is_tcp(false),
+ is_server(false),
+ first_read(false),
+ timeout(0),
+ theAutoGrowFlag(false)
+{
+
+ if (!init)
+ {
+ netInit(NULL, NULL); // plib-1.4.2 compatible
+ init = true;
+ }
+
+ save_buf.resize(2 * SG_IO_MAX_MSG_SIZE);
+ if ( style == "tcp" )
+ {
+ is_tcp = true;
+ }
+ else if ( style != "udp" )
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: SGSocket() unknown style = " << style );
+ }
+
+ set_type( sgSocketType );
+}
+
+SGSocket::SGSocket()
+ :SGIOChannel(),
+ hostname(""),
+ port_str(""),
+ save_len(0),
+ client(0),
+ is_tcp(false),
+ is_server(false),
+ first_read(false),
+ timeout(0),
+ theAutoGrowFlag(false)
+{
+ if (!init)
+ {
+ netInit(NULL, NULL); // plib-1.4.2 compatible
+ init = true;
+ }
+ save_buf.resize(2 * SG_IO_MAX_MSG_SIZE);
+ set_type( sgSocketType );
+}
+
+SGSocket::~SGSocket()
+{
+ this->close();
+}
+
+void SGSocket::setSocket(const string& host, const string& port, const string& style)
+{
+ close();
+ hostname = host;
+ port_str = port;
+ save_len = 0;
+ is_tcp = false;
+ is_server = false;
+ first_read = false;
+ timeout = 0;
+
+ if ( style == "tcp" )
+ {
+ is_tcp = true;
+ }
+ else if ( style != "udp" )
+ {
+ }
+}
+
+void SGSocket::setSocket(const string& host, int port, const string& style)
+{
+ close();
+ hostname = host;
+ port_str = ossimString::toString(port).string();
+ save_len = 0;
+ is_tcp = false;
+ is_server = false;
+ first_read = false;
+ timeout = 0;
+
+ if ( style == "tcp" )
+ {
+ is_tcp = true;
+ }
+ else if ( style != "udp" )
+ {
+ }
+}
+
+bool
+SGSocket::make_server_socket()
+{
+ if (!sock.open( is_tcp ))
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: socket() failed in make_server_socket()" );
+ return false;
+ }
+
+ if (sock.bind( "", port ) < 0)
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: bind() failed in make_server_socket()" );
+ sock.close();
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+SGSocket::make_client_socket()
+{
+ if (!sock.open( is_tcp ))
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: socket() failed in make_client_socket()" );
+ return false;
+ }
+
+ if (sock.connect( hostname.c_str(), port ) < 0)
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: connect() failed in make_client_socket()" );
+ sock.close();
+ return false;
+ }
+
+ return true;
+}
+
+// If specified as a server (in direction for now) open the master
+// listening socket. If specified as a client (out direction), open a
+// connection to a server.
+bool
+SGSocket::open( SGProtocolDir direction )
+{
+ set_dir( direction );
+
+ is_server = is_tcp &&
+ (direction == SG_IO_IN || direction == SG_IO_BI);
+
+ if ( port_str == "" || port_str == "any" ) {
+ port = 0;
+ } else {
+ port = atoi( port_str.c_str() );
+ }
+
+ if (direction == SG_IO_IN)
+ {
+ // this means server for now
+
+ // Setup socket to listen on. Set "port" before making this
+ // call. A port of "0" indicates that we want to let the os
+ // pick any available port.
+ if (!make_server_socket())
+ {
+// SG_LOG( SG_IO, SG_ALERT, "SG_IO_IN socket creation failed" );
+ return false;
+ }
+
+ if ( !is_tcp )
+ {
+ // Non-blocking UDP
+ nonblock();
+ }
+ else
+ {
+ // Blocking TCP
+ // Specify the maximum length of the connection queue
+ sock.listen( SG_MAX_SOCKET_QUEUE );
+ }
+
+ }
+ else if (direction == SG_IO_OUT)
+ {
+ // this means client for now
+
+ if (!make_client_socket())
+ {
+// SG_LOG( SG_IO, SG_ALERT, "SG_IO_OUT socket creation failed" );
+ return false;
+ }
+
+ if ( !is_tcp )
+ {
+ // Non-blocking UDP
+ nonblock();
+ }
+ }
+ else if (direction == SG_IO_BI && is_tcp)
+ {
+ // this means server for TCP sockets
+
+ // Setup socket to listen on. Set "port" before making this
+ // call. A port of "0" indicates that we want to let the os
+ // pick any available port.
+ if (!make_server_socket())
+ {
+// SG_LOG( SG_IO, SG_ALERT, "SG_IO_BI socket creation failed" );
+ return false;
+ }
+ // Blocking TCP
+ // Specify the maximum length of the connection queue
+ sock.listen( SG_MAX_SOCKET_QUEUE );
+ }
+ else
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: bidirection mode not available for UDP sockets." );
+ return false;
+ }
+
+ first_read = false;
+
+ return true;
+}
+
+
+// read data from socket (server)
+// read a block of data of specified size
+int
+SGSocket::read( char *buf, int length )
+{
+ if (sock.getHandle() == -1 &&
+ (client == 0 || client->getHandle() == -1))
+ {
+// std::cout << "HERE!!!!!" << std::endl;
+ return 0;
+ }
+
+ // test for any input available on sock (returning immediately, even if
+ // nothing)
+ int result = poll();
+
+ if (result > 0)
+ {
+ if (is_tcp && is_server)
+ {
+ result = client->recv( buf, length );
+ }
+ else
+ {
+ result = sock.recv( buf, length );
+ }
+
+ if ( result != length )
+ {
+// SG_LOG( SG_IO, SG_INFO,
+// "Warning: read() not enough bytes." );
+ }
+ }
+
+ return result;
+}
+
+
+// read a line of data, length is max size of input buffer
+int
+SGSocket::readline( char *buf, int /*length*/ )
+{
+ bool noMoreDataFlag = false;
+ if (sock.getHandle() == -1 &&
+ (client == 0 || client->getHandle() == -1))
+ {
+ return 0;
+ }
+ // test for any input read on sock (returning immediately, even if
+ // nothing)
+ int result = this->poll();
+ if (result > 0)
+ {
+ // read a chunk, keep in the save buffer until we have the
+ // requested amount read
+
+ if (is_tcp && is_server)
+ {
+ char *buf_ptr = &save_buf.front() + save_len;
+ result = client->recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
+
+ if ( result > 0 )
+ {
+ first_read = true;
+ }
+ save_len += result;
+
+ if(result < 0)
+ {
+ delete client;
+ client = 0;
+ noMoreDataFlag = true;
+ }
+ // Try and detect that the remote end died. This
+ // could cause problems so if you see connections
+ // dropping for unexplained reasons, LOOK HERE!
+ else if (result == 0 && save_len == 0 && first_read == true)
+ {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Connection closed by foreign host." );
+ delete client;
+ client = 0;
+ }
+ else if( (result == 0) && (first_read))
+ {
+ noMoreDataFlag = true;
+ }
+ }
+ else
+ {
+ char *buf_ptr = &save_buf.front() + save_len;
+ result = sock.recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
+ save_len += result;
+ }
+ }
+ // look for the end of line in save_buf
+ int i;
+ for ( i = 0; ((i < save_len) && (save_buf[i] != theReadlineDelimiter)); ++i );
+ if (save_buf[i] == theReadlineDelimiter )
+ {
+ result = i + 1;
+ }
+ else if(noMoreDataFlag)
+ {
+ if(save_len < 0)
+ {
+ save_len = 0;
+ result = 0;
+ }
+ else
+ {
+ result = save_len;
+ }
+ }
+ else
+ {
+ // no delimeter yet
+ return 0;
+ }
+
+ // we found a delimeter
+
+ // copy to external buffer
+ strncpy( buf, &save_buf.front(), result );
+ buf[result] = '\0';
+
+ // shift save buffer
+ //memmove( save_buf+, save_buf+, ? );
+ for ( i = result; i < save_len; ++i )
+ {
+ save_buf[ i - result ] = save_buf[i];
+ }
+// save_len -= result;
+ save_len = 0;
+
+ return result;
+}
+
+
+// write data to socket (client)
+int
+SGSocket::write( const char *buf, const int length )
+{
+ netSocket* s = client == 0 ? &sock : client;
+ if (s->getHandle() == -1)
+ {
+ return 0;
+ }
+
+ bool error_condition = false;
+
+ if ( s->send( buf, length ) < 0 )
+ {
+// SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
+ error_condition = true;
+ }
+
+ if ( error_condition ) {
+ return 0;
+ }
+
+ return length;
+}
+
+
+// write null terminated string to socket (server)
+int SGSocket::writestring( const char *str )
+{
+ int length = strlen( str );
+ return this->write( str, length );
+}
+
+
+// close the port
+bool SGSocket::close()
+{
+ if(client)
+ {
+ delete client;
+ client = 0;
+ }
+
+ sock.close();
+
+ return true;
+}
+
+
+// configure the socket as non-blocking
+bool
+SGSocket::nonblock()
+{
+ if (sock.getHandle() == -1) {
+ return false;
+ }
+
+ sock.setBlocking( false );
+ return true;
+}
+
+int
+SGSocket::poll()
+{
+ netSocket* readers[2];
+
+ readers[0] = client != 0 ? client : &sock;
+ readers[1] = 0;
+
+ netSocket* writers[1];
+ writers[0] = 0;
+
+ int result = netSocket::select( readers, writers, timeout );
+
+ if (result > 0 && is_server && client == 0)
+ {
+ // Accept a new client connection
+ netAddress addr;
+ int new_fd = sock.accept( &addr );
+// SG_LOG( SG_IO, SG_INFO, "Accepted connection from "
+// << addr.getHost() << ":" << addr.getPort() );
+ client = new netSocket();
+ client->setHandle( new_fd );
+ return 0;
+ }
+
+ return result;
+}
diff --git a/ossimPlanet/src/ossimPlanet/sg_socket_udp.cpp b/ossimPlanet/src/ossimPlanet/sg_socket_udp.cpp
new file mode 100644
index 0000000..9a0e245
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/sg_socket_udp.cpp
@@ -0,0 +1,200 @@
+// sg_socket.cxx -- Socket I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id: sg_socket_udp.cpp 11618 2007-08-15 18:48:57Z gpotts $
+
+#include <ossimPlanet/compiler.h>
+
+#if defined( sgi )
+#include <strings.h>
+#endif
+
+
+#include <ossimPlanet/sg_socket_udp.h>
+
+
+SGSocketUDP::SGSocketUDP( const string& host, const string& port ) :
+ hostname(host),
+ port_str(port),
+ save_len(0)
+{
+ set_valid( false );
+}
+
+
+SGSocketUDP::~SGSocketUDP() {
+}
+
+
+// If specified as a server (in direction for now) open the master
+// listening socket. If specified as a client (out direction), open a
+// connection to a server.
+bool SGSocketUDP::open( const SGProtocolDir d ) {
+ set_dir( d );
+
+ if ( ! sock.open( false ) ) { // open a UDP socket
+// SG_LOG( SG_IO, SG_ALERT, "error opening socket" );
+ return false;
+ }
+
+ if ( port_str == "" || port_str == "any" ) {
+ port = 0;
+ } else {
+ port = atoi( port_str.c_str() );
+ }
+
+ // client_connections.clear();
+
+ if ( get_dir() == SG_IO_IN ) {
+ // this means server
+
+ // bind ...
+ if ( sock.bind( hostname.c_str(), port ) == -1 ) {
+// SG_LOG( SG_IO, SG_ALERT, "error binding to port" << port_str );
+ return false;
+ }
+ } else if ( get_dir() == SG_IO_OUT ) {
+ // this means client
+
+ // connect ...
+ if ( sock.connect( hostname.c_str(), port ) == -1 ) {
+// SG_LOG( SG_IO, SG_ALERT,
+// "error connecting to " << hostname << port_str );
+ return false;
+ }
+ } else {
+// SG_LOG( SG_IO, SG_ALERT,
+// "Error: bidirection mode not available for UDP sockets." );
+ return false;
+ }
+
+ set_valid( true );
+
+ return true;
+}
+
+
+// read data from socket (server)
+// read a block of data of specified size
+int SGSocketUDP::read( char *buf, int /*length*/ ) {
+ if ( ! isvalid() ) {
+ return 0;
+ }
+
+ int result;
+
+ if ( (result = sock.recv(buf, SG_IO_MAX_MSG_SIZE, 0)) >= 0 ) {
+ buf[result] = '\0';
+ // printf("msg received = %s\n", buf);
+ }
+
+ return result;
+}
+
+
+// read a line of data, length is max size of input buffer
+int SGSocketUDP::readline( char *buf, int /*length*/ ) {
+ if ( ! isvalid() ) {
+ return 0;
+ }
+
+ // cout << "sock = " << sock << endl;
+
+ char *buf_ptr = save_buf + save_len;
+ int result = sock.recv(buf_ptr, SG_IO_MAX_MSG_SIZE, 0);
+ // printf("msg received = %s\n", buf);
+ save_len += result;
+
+ // look for the end of line in save_buf
+ int i;
+ for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i );
+ if ( save_buf[i] == '\n' ) {
+ result = i + 1;
+ } else {
+ // no end of line yet
+ // cout << "no eol found" << endl;
+ return 0;
+ }
+ // cout << "line length = " << result << endl;
+
+ // we found an end of line
+
+ // copy to external buffer
+ strncpy( buf, save_buf, result );
+ buf[result] = '\0';
+ // cout << "sg_socket line = " << buf << endl;
+
+ // shift save buffer
+ for ( i = result; i < save_len; ++i ) {
+ save_buf[ i - result ] = save_buf[i];
+ }
+ save_len -= result;
+
+ return result;
+}
+
+
+// write data to socket (client)
+int SGSocketUDP::write( const char *buf, const int length ) {
+ if ( ! isvalid() ) {
+ return 0;
+ }
+
+ bool error_condition = false;
+
+ if ( sock.send( buf, length, 0 ) < 0 ) {
+// SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
+ error_condition = true;
+ return 0;
+ }
+
+ return length;
+}
+
+
+// write null terminated string to socket (server)
+int SGSocketUDP::writestring( const char *str ) {
+ if ( !isvalid() ) {
+ return 0;
+ }
+
+ int length = strlen( str );
+ return write( str, length );
+}
+
+
+// close the port
+bool SGSocketUDP::close() {
+ if ( !isvalid() ) {
+ return 0;
+ }
+
+ sock.close();
+
+ return true;
+}
+
+
+// configure the socket as non-blocking
+bool SGSocketUDP::setBlocking( bool value ) {
+ sock.setBlocking( value );
+
+ return true;
+}
diff --git a/ossimPlanet/src/ossimPlanet/ul.cpp b/ossimPlanet/src/ossimPlanet/ul.cpp
new file mode 100644
index 0000000..0ce529d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ul.cpp
@@ -0,0 +1,544 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ul.cxx 2129 2007-10-16 00:45:26Z fayjf $
+*/
+
+
+#include <ossimPlanet/ul.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef UL_MSVC
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif
+
+#ifdef UL_MSVC
+#define SLASH "\\"
+#else
+#define SLASH "/"
+#endif
+
+
+struct _ulDir
+{
+ char dirname [ UL_NAME_MAX+1 ];
+ ulDirEnt curr ;
+
+#ifdef UL_MSVC
+ WIN32_FIND_DATA data ;
+ HANDLE hFind ;
+ bool first ;
+ bool done ;
+#else
+ DIR *dirp ;
+#endif
+} ;
+
+
+void ulInit ()
+{
+}
+
+
+ulDir* ulOpenDir ( const char* dirname )
+{
+ ulDir* dir = new ulDir;
+ if ( dir != NULL )
+ {
+ strcpy( dir->dirname, dirname ) ;
+
+#ifdef UL_MSVC
+ char search[_MAX_PATH];
+ strcpy(search,dirname);
+
+ //munch the directory seperator
+ int len = strlen(search);
+ if ( len>0 && strchr("/\\",search[len-1]) )
+ search[len-1] = 0;
+
+ //add the wildcard
+ strcat(search,"/*.*");
+
+ dir->first = true;
+ dir->done = false;
+ dir->hFind = FindFirstFile(search, &dir->data);
+ if (dir->hFind == INVALID_HANDLE_VALUE)
+ {
+ delete dir;
+ dir = NULL;
+ }
+#else
+ dir->dirp = opendir(dirname) ;
+
+ if ( dir->dirp == NULL )
+ {
+ delete dir ;
+ dir = NULL ;
+ }
+#endif
+ }
+ return dir;
+}
+
+
+ulDirEnt* ulReadDir ( ulDir* dir )
+{
+ //read the next entry from the directory
+#ifdef UL_MSVC
+ //update state
+ if ( dir->first )
+ dir->first = false ;
+ else if ( !dir->done && !FindNextFile(dir->hFind,&dir->data) )
+ dir->done = true ;
+ if ( dir->done )
+ return NULL ;
+
+ strcpy( dir->curr.d_name, dir->data.cFileName ) ;
+#else
+ struct dirent* direntp = readdir( dir->dirp );
+ if ( !direntp )
+ return NULL ;
+
+ strcpy( dir->curr.d_name, direntp->d_name );
+#endif
+
+ //determine if this entry is a directory
+#ifdef UL_MSVC
+ dir->curr.d_isdir = ( dir->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0;
+ #else
+ char path[ 1000 + UL_NAME_MAX+1 ];
+ sprintf( path, "%s/%s", dir->dirname, dir->curr.d_name );
+ struct stat buf ;
+ if ( stat(path,&buf) == 0 )
+ dir->curr.d_isdir = (buf.st_mode & S_IFDIR) != 0 ;
+ else
+ dir->curr.d_isdir = false ;
+#endif
+
+ return( &dir->curr ) ;
+}
+
+
+
+void ulCloseDir ( ulDir* dir )
+{
+ if ( dir != NULL )
+ {
+#ifdef UL_MSVC
+ FindClose(dir->hFind);
+#else
+ closedir ( dir->dirp ) ;
+#endif
+ delete dir ;
+ }
+}
+
+bool ulFileExists ( const char *fileName )
+{
+#ifdef UL_MSVC
+ struct _stat buf ;
+
+ if ( _stat ( fileName, &buf ) < 0 )
+ return false ;
+
+ return ((S_IFREG & buf.st_mode ) !=0) ;
+#else
+ struct stat buf ;
+
+ if ( stat ( fileName, &buf ) < 0 )
+ return false ;
+
+ return ((S_ISREG ( buf.st_mode )) != 0) ;
+#endif
+}
+
+char* ulMakePath( char* path, const char* dir, const char* fname )
+{
+ if ( fname )
+ {
+ if ( !ulIsAbsolutePathName (fname) &&
+ dir != NULL && dir[0] != '\0' )
+ {
+ strcpy ( path, dir ) ;
+ strcat ( path, SLASH ) ;
+ strcat ( path, fname ) ;
+ }
+ else
+ strcpy ( path, fname ) ;
+ }
+ else
+ path [0] = 0 ;
+ return( path );
+}
+
+
+static int recursiveFindFileInSubDirs ( char * filenameOutput,
+ const char * tPath, const char * tfnameInput )
+{
+ int bFound = FALSE;
+ char tempString [ 1024 ];
+
+ ulMakePath ( filenameOutput, tPath, tfnameInput ) ;
+
+ if ( ulFileExists ( filenameOutput ) )
+ return TRUE;
+
+ ulDir* dirp = ulOpenDir(tPath);
+
+ if ( dirp != NULL )
+ {
+ ulDirEnt* dp;
+
+ while ( ! bFound && ((dp = ulReadDir(dirp)) != NULL ) )
+ {
+ // I am doing recursive ulOpenDir/ulReadDirs here.
+ // I know this works under Windo$.
+ if ( dp->d_isdir &&
+ strcmp( dp->d_name, ".") != 0 &&
+ strcmp( dp->d_name, "..") != 0 )
+ {
+ ulMakePath ( tempString, tPath, dp->d_name) ;
+ bFound = recursiveFindFileInSubDirs ( filenameOutput,
+ tempString, tfnameInput );
+ }
+
+ }
+ ulCloseDir ( dirp ) ;
+ }
+
+ return bFound;
+}
+
+
+
+void ulFindFile( char *filenameOutput, const char *path,
+ const char * tfnameInput, const char *sAPOM )
+/*
+ adds tfnameInput to the path and puts this into the buffer filenameOutput.
+ sAPOM is used iff path contains "$(APOM)"
+
+ handles special chars in path:
+
+ ";;" is replaced by ";"
+ "$$" is replaced by "$"
+ "$(APOM)" is replaced by sAPOM
+
+ If there are ";" in path, the path-variable is interpreted as several
+ paths "segments", delimited by ";". The first file found by this function
+ is returned.
+
+ It looks from left to right.
+
+ A segment may end in $(...). ulFindFile will then look in in this
+ path and recursively in all the sub-paths
+
+ Some examples:
+
+ for loading *.MDl-models, it is very nice to set the texture path to
+
+ $(APOM);$(APOM)/texture;$(APOM)/../texture
+
+ This consits of three segments and tells ulFindFile to look in the
+ path of the model, in a subpath texture and in a path texture "besides"
+ the path of the model. Some *.mdl-models are shipped in a directory which
+ conatins a "texture"-directory, a "Model"-directory and others. In this
+ case you find the texture in $(APOM)/../texture
+
+ Another example: You have all your textures in a directory-structure
+ under /roomplan. For example brick is under /roomplan/bricks, wood is
+ under /roomplan/wood, oak is under /roomplan/wood/oak. Then you should
+ use the following texture path:
+
+ "/roomplan/$(...)"
+
+ If you dont want all of the bells and whistles, just call:
+ _ssgMakePath ( filenameOutput, path, tfnameInput ) ;
+*/
+
+{
+
+ char temp_texture_path[1024], *s_ptr, *s_ptr1, *current_path;
+
+ strncpy(temp_texture_path, path, 1024);
+ current_path = temp_texture_path;
+ s_ptr = temp_texture_path;
+
+ while ( *s_ptr != 0 )
+ {
+ if ( *s_ptr == ';' )
+ {
+ if ( s_ptr [ 1 ] == ';' )
+ {
+ // replace ";;" with ";"
+ s_ptr1 = ++s_ptr; // both pointers on second ";"
+
+ while ( *s_ptr1 != 0)
+ { s_ptr1 [ 0 ] = s_ptr1 [ 1 ];
+ s_ptr1++;
+ }
+ }
+ else
+ {
+ // found a single ';'. This delimits paths
+ *s_ptr++ = 0;
+ ulMakePath ( filenameOutput, current_path, tfnameInput ) ;
+
+ if ( ulFileExists ( filenameOutput ) )
+ return; // success!
+
+ // this path doesnt hold the texture. Try next one
+ current_path = s_ptr;
+ }
+ }
+ else if ( *s_ptr == '$' )
+ {
+ if ( s_ptr [ 1 ] == '$' )
+ {
+ // replace "$$" with "$"
+ s_ptr1 = ++s_ptr; // both pointers on second "$"
+
+ while ( *s_ptr1 != 0)
+ {
+ s_ptr1 [ 0 ] = s_ptr1 [ 1 ];
+ s_ptr1++;
+ }
+ }
+ else
+ if ( 0 == strncmp( s_ptr, "$(APOM)", strlen("$(APOM)" ) ) )
+ {
+ // replace "$(APOM)" by sAPOM
+ char temp_buffer[1024];
+ * s_ptr = 0;
+ s_ptr += strlen ( "$(APOM)" );
+ strcpy ( temp_buffer, s_ptr );
+ strcat ( current_path, sAPOM);
+ s_ptr = & current_path [ strlen(current_path) ] ; // onto the 0
+ strcat ( current_path, temp_buffer );
+ }
+ else
+ if ( 0 == strncmp( s_ptr, "$(...)", strlen("$(...)" ) ) )
+ {
+ //strcpy(temp_texture_path_for_recursion, current_path);
+
+ char * nextPath=s_ptr;
+ nextPath += strlen("$(...)" );
+
+ while (*nextPath != 0 )
+ {
+ if ( *nextPath == ';' )
+ {
+ if ( nextPath[1] == ';' )
+ nextPath++; // so its "add 2 " togehter with the ++ further down
+ else
+ {
+ *nextPath = 0;
+ break; // breaks the while
+ }
+ }
+ nextPath++;
+ }
+
+ // This segment of the path ends with a 0 now
+ // *****
+
+ char tPath [ 1024 ];
+ strcpy ( tPath, current_path ) ;
+ tPath [ (long) (s_ptr - current_path) ] = 0;
+
+ // So, lets recurse into the sub-dirs:
+ // Here I just assume that the "$(...)" is the last thing in
+ // this segment
+
+ if ( recursiveFindFileInSubDirs ( filenameOutput,
+ tPath, tfnameInput ) )
+ return ; // success
+
+ // *****
+ // we handled the path-segment current_path containing the $(...) and
+ // didnt find the file, so go on to the nect segment
+
+ current_path = nextPath; // points to a 0 if this was the last segment
+ s_ptr = current_path;
+ }
+ else
+ s_ptr++;
+ }
+ else // neither ';' nor '$'
+ s_ptr++;
+ }
+
+ ulMakePath ( filenameOutput, current_path, tfnameInput ) ; // pfusch? kludge?
+}
+
+///////////////////// string handling ///////////////////////////////
+
+/*
+ Strdup is *evil* - use this instead...
+*/
+
+char *ulStrDup ( const char *s )
+{
+ int s_sz = strlen ( s ) + 1 ;
+ char *ret = new char [ s_sz ] ;
+
+ memcpy ( ret, s, s_sz ) ;
+ return ret ;
+}
+
+
+
+// string comparisons that are *not* case sensitive:
+
+/*
+
+
+ I'm sick of half the machines on the planet supporting
+ strncasecmp and the other half strnicmp - so here is my own
+ offering.
+
+ **** ATTENTION ****
+ WK: If you used strnicmp, make sure you realise the completely
+ changed meaning of the return value - 0 means not equal!
+*/
+
+int ulStrNEqual ( const char *s1, const char *s2, int len )
+{
+ int l1 = (s1==NULL) ? 0 : strlen ( s1 ) ;
+ int l2 = (s2==NULL) ? 0 : strlen ( s2 ) ;
+
+ if ( l1 > len ) l1 = len ;
+
+ if ( l2 < l1 || l1 < len )
+ return FALSE ;
+
+ for ( int i = 0 ; i < l1 ; i++ )
+ {
+ char c1 = s1[i] ;
+ char c2 = s2[i] ;
+
+ if ( c1 == c2 )
+ continue ;
+
+ if ( c1 >= 'a' && c1 <= 'z' )
+ c1 = c1 - ('a'-'A') ;
+
+ if ( c2 >= 'a' && c2 <= 'z' )
+ c2 = c2 - ('a'-'A') ;
+
+ if ( c1 != c2 )
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+
+/*
+ I'm sick of half the machines on the planet supporting
+ strcasecmp and the other half stricmp - so here is my own
+ offering.
+
+ **** ATTENTION ****
+ WK: If you used stricmp, make sure you realise the completely
+ changed meaning of the return value - 0 means not equal!
+*/
+
+int ulStrEqual ( const char *s1, const char *s2 )
+{
+ int l1 = (s1==NULL) ? 0 : strlen ( s1 ) ;
+ int l2 = (s2==NULL) ? 0 : strlen ( s2 ) ;
+
+ if ( l1 != l2 ) return FALSE ;
+
+ for ( int i = 0 ; i < l1 ; i++ )
+ {
+ char c1 = s1[i] ;
+ char c2 = s2[i] ;
+
+ if ( c1 == c2 )
+ continue ;
+
+ if ( c1 >= 'a' && c1 <= 'z' )
+ c1 -= ('a'-'A') ;
+
+ if ( c2 >= 'a' && c2 <= 'z' )
+ c2 -= ('a'-'A') ;
+
+ if ( c1 != c2 )
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+
+int ulIsAbsolutePathName ( const char *pathname )
+{
+ /*
+ Is this an absolute pathname or a relative one?
+ */
+
+ if ( (pathname == NULL) || (pathname [0] == 0) )
+ return FALSE;
+
+#ifdef UL_MSVC
+
+ /*
+ Under WinDOS, it's an absolute path if it starts
+ with a slash *or* if it starts with a drive letter,
+ a colon and a slash.
+ */
+
+ return ( pathname[0] == SLASH[0] || pathname[0] == '/' ) ||
+ (
+ (
+ ( pathname[0] >= 'a' && pathname[0] <= 'z' ) ||
+ ( pathname[0] >= 'A' && pathname[0] <= 'Z' )
+ ) &&
+ pathname[1] == ':' &&
+ ( pathname[2] == SLASH[0] || pathname[2] == '/' )
+ ) ;
+#elif defined(UL_MACINTOSH)
+ return (pathname [0] != ':' && strchr( pathname, ':') != NULL );
+#else
+ return pathname [0] == SLASH[0] ;
+#endif
+}
+
+
+char *ulGetCWD ( char *result, int maxlength )
+{
+ /*
+ Return the current working directory into 'result' - which
+ has enough space for 'maxlength-1' characters and a '\0'.
+ */
+
+#ifdef UL_MSVC
+ return _getcwd ( result, maxlength ) ;
+#else
+ return getcwd ( result, maxlength ) ;
+#endif
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ulClock.cpp b/ossimPlanet/src/ossimPlanet/ulClock.cpp
new file mode 100644
index 0000000..972bc8d
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ulClock.cpp
@@ -0,0 +1,117 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ulClock.cxx 1735 2002-12-01 18:21:48Z sjbaker $
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ossimPlanet/ul.h>
+
+#ifdef UL_CYGWIN
+ typedef long long _int64;
+ #define LARGEINTEGER _int64
+#endif
+
+#ifndef UL_WIN32
+# include <sys/time.h>
+#endif
+
+#include <time.h>
+
+#ifdef UL_WIN32
+
+double ulClock::res ;
+int ulClock::perf_timer = -1;
+
+void ulClock::initPerformanceTimer ()
+{
+ if ( perf_timer == -1 )
+ {
+ /* Use Performance Timer if it's available, mmtimer if not. */
+
+ __int64 frequency ;
+
+ perf_timer = QueryPerformanceFrequency ( (LARGE_INTEGER *) & frequency ) ;
+
+ if ( perf_timer )
+ {
+ res = 1.0 / (double) frequency ;
+ perf_timer = 1 ;
+ }
+ }
+}
+#endif
+
+double ulClock::getRawTime () const
+{
+#ifdef UL_WIN32
+
+ /* Use Performance Timer if it's available, mmtimer if not. */
+
+ if ( perf_timer )
+ {
+ __int64 t ;
+
+ QueryPerformanceCounter ( (LARGE_INTEGER *) &t ) ;
+
+ return res * (double) t ;
+ }
+
+ return (double) timeGetTime() * 0.001 ;
+
+#else
+ timeval tv ;
+
+ gettimeofday ( & tv, NULL ) ;
+
+ return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
+#endif
+}
+
+
+void ulClock::update ()
+{
+ now = getRawTime() - start ;
+
+ delta = now - last_time ;
+
+ /*
+ KLUDGE: If the frame rate drops below ~5Hz, then
+ control will be very difficult. It's
+ actually easier to give up and slow
+ down the action. max_delta defaults to
+ 200ms for that reason.
+
+ KLUDGE: If update is called very rapidly, then
+ delta can be zero which causes some
+ programs to div0. So we'll clamp to
+ a millionth of a second.
+ */
+
+ if ( delta > max_delta ) delta = max_delta ;
+ if ( delta <= 0.0 ) delta = 0.0000001 ;
+
+ last_time = now ;
+}
+
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ulError.cpp b/ossimPlanet/src/ossimPlanet/ulError.cpp
new file mode 100644
index 0000000..2eb50a7
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ulError.cpp
@@ -0,0 +1,90 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ulError.cxx 1967 2004-10-02 12:20:43Z wolfram_kuss $
+*/
+
+
+#include <ossimPlanet/ul.h>
+
+static char _ulErrorBuffer [ 1024 ] = { '\0' } ;
+static ulErrorCallback _ulErrorCB = 0 ;
+
+static const char* _ulSeverityText [ UL_MAX_SEVERITY ] =
+{
+ "DEBUG",
+ "WARNING",
+ "FATAL",
+};
+
+
+void ulSetError ( enum ulSeverity severity, const char *fmt, ... )
+{
+ va_list argp;
+ va_start ( argp, fmt ) ;
+ vsprintf ( _ulErrorBuffer, fmt, argp ) ;
+ va_end ( argp ) ;
+
+ if ( _ulErrorCB )
+ {
+ (*_ulErrorCB)( severity, _ulErrorBuffer ) ;
+ }
+ else
+ {
+ fprintf ( stderr, "%s: %s\n",
+ _ulSeverityText[ severity ], _ulErrorBuffer ) ;
+ if ( severity == UL_FATAL )
+ {
+#ifdef WIN32
+ // A Windows user that does not start the program from the command line
+ // will not see output to stderr
+ ::MessageBox(0, _ulErrorBuffer, "fatal error!:", 0);
+#endif
+ exit (1) ;
+ }
+ }
+}
+
+
+char* ulGetError ( void )
+{
+ return _ulErrorBuffer ;
+}
+
+
+void ulClearError ( void )
+{
+ _ulErrorBuffer [0] = 0 ;
+}
+
+
+ulErrorCallback ulGetErrorCallback ( void )
+{
+ return _ulErrorCB ;
+}
+
+
+void ulSetErrorCallback ( ulErrorCallback cb )
+{
+ _ulErrorCB = cb ;
+}
+
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ulLinkedList.cpp b/ossimPlanet/src/ossimPlanet/ulLinkedList.cpp
new file mode 100644
index 0000000..0664d10
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ulLinkedList.cpp
@@ -0,0 +1,272 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ulLinkedList.cxx 1568 2002-09-02 06:05:49Z sjbaker $
+*/
+
+
+#include <ossimPlanet/ulLocal.h>
+
+void ulLinkedList::unlinkNode ( ulListNode *prev, ulListNode *node )
+{
+ /* Is this the first node ? */
+ if ( prev == NULL )
+ head = node -> getNext () ;
+ else
+ prev -> setNext ( node -> getNext () ) ;
+
+ /* Is this the last node ? */
+ if ( node -> getNext () == NULL )
+ tail = prev ;
+}
+
+
+int ulLinkedList::getNodePosition ( void *data ) const
+{
+ ulListNode *curr = head ;
+ int pos = 0 ;
+
+ while ( curr != NULL )
+ {
+ if ( curr -> getData () == data )
+ return pos ;
+
+ pos++ ;
+ curr = curr -> getNext () ;
+ }
+
+ return -1 ;
+}
+
+
+void ulLinkedList::appendNode ( void *data )
+{
+ ulListNode *new_node = new ulListNode ( data, NULL ) ;
+
+ if ( head == NULL )
+ head = new_node ;
+ else
+ tail -> setNext ( new_node ) ;
+
+ tail = new_node ;
+
+ if ( ++nnodes > 1 )
+ sorted = false ;
+}
+
+void ulLinkedList::insertNode ( void *data, int pos )
+{
+ if ( pos == 0 )
+ {
+ head = new ulListNode ( data, head ) ;
+
+ if ( tail == NULL )
+ tail = head ;
+ }
+ else
+ {
+ if ( ! isValidPosition ( pos ) )
+ return ;
+ else
+ {
+ ulListNode *prev = head ;
+
+ while ( --pos > 0 )
+ prev = prev -> getNext () ;
+
+ prev -> setNext ( new ulListNode ( data, prev -> getNext () ) ) ;
+ }
+ }
+
+ if ( ++nnodes > 1 )
+ sorted = false ;
+}
+
+
+int ulLinkedList::insertSorted ( void *data, ulCompareFunc comparefn )
+{
+ if ( comparefn != NULL )
+ {
+ if ( sorted )
+ {
+ int pos = 0 ;
+
+ if ( head == NULL )
+ head = tail = new ulListNode ( data, NULL ) ;
+ else
+ {
+ ulListNode *curr = head, *prev = NULL ;
+
+ while ( (*comparefn)( curr -> getData (), data ) < 0 )
+ {
+ prev = curr ;
+ curr = curr -> getNext () ;
+
+ pos++ ;
+
+ if ( curr == NULL )
+ {
+ tail = new ulListNode ( data, curr ) ;
+ prev -> setNext ( tail ) ;
+
+ nnodes++ ;
+ return pos ;
+ }
+ }
+
+ if ( prev == NULL )
+ head = new ulListNode ( data, head ) ;
+ else
+ prev -> setNext ( new ulListNode ( data, curr ) ) ;
+ }
+
+ nnodes++ ;
+ return pos ;
+ }
+ else
+ ulSetError ( UL_WARNING,
+ "ulLinkedList::insertSorted: This is not a sorted list !" ) ;
+ }
+
+ return -1 ;
+}
+
+
+void ulLinkedList::removeNode ( void *data )
+{
+ ulListNode *curr = head, *prev = NULL ;
+
+ while ( curr != NULL )
+ {
+ if ( curr -> getData () == data )
+ {
+ unlinkNode ( prev, curr ) ;
+
+ delete curr ;
+
+ if ( --nnodes <= 0 )
+ sorted = true ;
+
+ return ;
+ }
+
+ prev = curr ;
+ curr = curr -> getNext () ;
+ }
+
+ ulSetError ( UL_WARNING, "ulLinkedList::removeNode: No such node" ) ;
+}
+
+void * ulLinkedList::removeNode ( int pos )
+{
+ if ( ! isValidPosition ( pos ) )
+ return NULL ;
+
+ ulListNode *curr = head, *prev = NULL ;
+
+ while ( pos-- > 0 )
+ {
+ prev = curr ;
+ curr = curr -> getNext () ;
+ }
+
+ unlinkNode ( prev, curr ) ;
+
+ void *datap = curr -> getData () ;
+
+ delete curr ;
+
+ if ( --nnodes <= 1 )
+ sorted = true ;
+
+ return datap ;
+}
+
+
+void * ulLinkedList::getNodeData ( int pos ) const
+{
+ if ( ! isValidPosition ( pos ) )
+ return NULL ;
+
+ ulListNode *node ;
+
+ if ( pos == nnodes - 1 )
+ node = tail ;
+ else
+ {
+ node = head ;
+
+ while ( pos-- > 0 )
+ node = node -> getNext () ;
+ }
+
+ return node -> getData () ;
+}
+
+
+void * ulLinkedList::forEach ( ulIterateFunc fn, void *user_data ) const
+{
+ if ( fn != NULL )
+ {
+ ulListNode *curr ;
+
+ for ( curr = head ; curr != NULL ; curr = curr -> getNext () )
+ {
+ if ( (*fn)( curr -> getData (), user_data ) == false )
+ return curr -> getData () ;
+ }
+ }
+
+ return NULL ;
+}
+
+
+void ulLinkedList::empty ( ulIterateFunc destroyfn, void *user_data )
+{
+ ulListNode *curr = head ;
+
+ if ( destroyfn != NULL )
+ {
+ while ( curr != NULL )
+ {
+ ulListNode *next = curr -> getNext () ;
+
+ (*destroyfn) ( curr -> getData (), user_data ) ;
+
+ delete curr ;
+ curr = next ;
+ }
+ }
+ else
+ {
+ while ( curr != NULL )
+ {
+ ulListNode *next = curr -> getNext () ;
+
+ delete curr ;
+ curr = next ;
+ }
+ }
+
+ head = tail = NULL ;
+ nnodes = 0 ;
+ sorted = true ;
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/ulList.cpp b/ossimPlanet/src/ossimPlanet/ulList.cpp
new file mode 100644
index 0000000..418db54
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ulList.cpp
@@ -0,0 +1,109 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net
+
+ $Id: ulList.cxx 1732 2002-11-30 00:41:50Z sjbaker $
+*/
+
+
+#include <ossimPlanet/ul.h>
+
+
+ulList::ulList ( int init )
+{
+ total = 0 ;
+ next = 0 ;
+ entity_list = new void * [ limit = (init <= 0) ? 1 : init ] ;
+}
+
+
+ulList::~ulList (void)
+{
+ removeAllEntities () ;
+ delete [] entity_list ;
+}
+
+
+void ulList::addEntity ( void *entity )
+{
+ sizeChk () ;
+ entity_list [ total++ ] = entity ;
+}
+
+
+void ulList::addEntityBefore ( int i, void *entity )
+{
+ sizeChk () ;
+ memmove ( &entity_list[i+1], &entity_list[i], sizeof(void *) * (total-i) ) ;
+ entity_list [ i ] = entity ;
+ total++ ;
+}
+
+
+void ulList::sizeChk (void)
+{
+ /* Room for one more Entity? */
+
+ if ( total >= limit )
+ {
+ limit += limit ;
+ void **nlist = new void * [ limit ] ;
+ memmove ( nlist, entity_list, sizeof(void *) * total ) ;
+ delete [] entity_list ;
+ entity_list = nlist ;
+ }
+}
+
+
+int ulList::searchForEntity ( void *entity ) const
+{
+ for ( unsigned int i = 0 ; i < total ; i++ )
+ if ( entity_list [ i ] == entity )
+ return (int) i ;
+
+ return -1 ;
+}
+
+void ulList::removeAllEntities ()
+{
+ while ( total > 0 )
+ removeEntity ( (unsigned int) 0 ) ;
+}
+
+void ulList::removeEntity ( unsigned int n )
+{
+ memmove ( &(entity_list[n]), &(entity_list[n+1]),
+ sizeof(void *) * (total-n-1) ) ;
+ total-- ;
+
+ if ( next >= n )
+ next-- ;
+}
+
+
+
+void ulList::replaceEntity ( unsigned int n, void *new_entity )
+{
+ if ( n >= 0 )
+ entity_list [ n ] = new_entity;
+ else
+ addEntity ( new_entity ) ;
+}
+
+
diff --git a/ossimPlanet/src/ossimPlanet/ulRTTI.cpp b/ossimPlanet/src/ossimPlanet/ulRTTI.cpp
new file mode 100644
index 0000000..11c9ac0
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/ulRTTI.cpp
@@ -0,0 +1,109 @@
+/*
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ For further information visit http://plib.sourceforge.net */
+
+
+#include <ossimPlanet/ulRTTI.h>
+
+/* Originally written by: Alexandru C. Telea <alext at win.tue.nl> */
+
+
+static const ulRTTITypeinfo *RTTI_base_null_type [] = { 0 } ;
+
+const ulRTTITypeinfo* ulRTTIdyntypeid::a[] = { 0 } ;
+
+const ulRTTITypeinfo ulRTTITypeinfo::null_type ( "NULL", RTTI_base_null_type,
+ 0, 0 ) ;
+
+
+ulRTTITypeinfo::ulRTTITypeinfo ( const char *name, const ulRTTITypeinfo *bb[],
+ void* (*f1)(int,void*),void* (*f2)() )
+{
+ /* Create default ulRTTITypeinfo */
+ n = ulStrDup ( name ) ;
+
+ b = bb ; /* ns = 0 ; subtypes = 0 ; */
+
+ cast = f1 ; /* Attach casting func */
+ new_obj = f2 ; /* Attach creation func */
+
+ for ( int i = 0 ; b[i] ; i++ )
+ /* Add this as subtype to all its basetypes */
+ /* REMARK: Harmless const castaway */
+ ((ulRTTITypeinfo**)b)[i]->add_subtype ( this ) ;
+}
+
+ulRTTITypeinfo::~ulRTTITypeinfo ()
+{
+ delete [] n ;
+ for ( int i = 0 ; b[i] ; i++ )
+ /* Del this subtype from all its basetypes */
+ /* REMARK: Harmless const castaway */
+ ((ulRTTITypeinfo**)b)[i]->del_subtype ( this ) ;
+}
+
+void ulRTTITypeinfo::add_subtype ( const ulRTTITypeinfo *t )
+/*
+ Adds t as last ulRTTITypeinfo in the 'subtypes' list. For this, the list is
+ realloc'd with one extra entry.
+*/
+{
+ const ulRTTITypeinfo **ptr = new const ulRTTITypeinfo*[ns+1] ;
+ int i ; for ( i = 0 ; i < ns ; i++ ) ptr[i] = subtypes[i] ;
+ ptr[i] = t ;
+ ns++ ;
+ delete[] subtypes ;
+ subtypes = ptr ;
+}
+
+void ulRTTITypeinfo::del_subtype ( const ulRTTITypeinfo* t )
+/* Searches for t in the subtypes list of this and removes it, if found. */
+{
+ int i ; for ( i = 0 ; i < ns && subtypes[i] != t ; i++ ) ;
+ if ( i < ns )
+ for(; i < ns-1 ; i++ ) subtypes[i] = subtypes[i+1] ;
+}
+
+void * ulRTTITypeinfo::create ( const ulRTTITypeinfo* bt, const char *c ) const
+/*
+ Tries to create an obj of type-name given by char*. Searches for this type
+ in the type-DAG rooted by this, creates it and returns it as cast to 'bt',
+ where bt is either this or a direct base of this.
+*/
+{
+ void *p = NULL ; int i ;
+
+ if ( !strcmp ( c, n ) ) /* Want to create an obj of this type ? */
+ /* Yes, do it if this type is instantiable. */
+ p = (new_obj) ? new_obj () : 0 ;
+ else /* No, try with subclasses... */
+ for ( i = 0 ; i < ns &&
+ !( ( p = subtypes[i]->create ( this, c ) ) ) ; i++ ) ;
+ /* Succeeded creating on ith subclass branch ? */
+ if ( !p ) return 0 ; /* Couldn't create it in any way, abort. */
+ if ( bt == this )
+ i = -1 ; /* Must cast to this's own type (i==-1) */
+ else
+ /* Search to which base of this we should cast */
+ for ( i = 0 ; b[i] && b[i] != bt ; i++ ) ;
+
+ /* Found: cast to ith base of this */
+ return cast(i,p) ; /* Cast to ith base of to this, return as void* */
+}
+
diff --git a/ossimPlanet/src/ossimPlanet/unzip.c b/ossimPlanet/src/ossimPlanet/unzip.c
new file mode 100644
index 0000000..5f1e7b4
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/unzip.c
@@ -0,0 +1,1630 @@
+/* unzip.c -- IO for uncompress .zip files using zlib
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ Read unzip.h for more info
+*/
+
+/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+compatibility with older software. The following is from the original crypt.c. Code
+woven in by Terry Thorsen 1/2003.
+*/
+/*
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+ */
+
+/*
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include <ossimPlanet/unzip.h>
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+#ifndef CASESENSITIVITYDEFAULT_NO
+# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+# define CASESENSITIVITYDEFAULT_NO
+# endif
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+
+
+const char unz_copyright[] =
+ " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+ uLong offset_curfile;/* relative offset of local header 4 bytes */
+} unz_file_info_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+typedef struct
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+ uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ uLong offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ uLong pos_local_extrafield; /* position in the local extra field in read*/
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ uLong rest_read_compressed; /* number of byte to be decompressed */
+ uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ zlib_filefunc_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ zlib_filefunc_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ unz_global_info gi; /* public global information */
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ uLong num_file; /* number of the current file in the zipfile*/
+ uLong pos_in_central_dir; /* pos of the current file in the central dir*/
+ uLong current_file_ok; /* flag about the usability of the current file*/
+ uLong central_pos; /* position of the beginning of the central dir*/
+
+ uLong size_central_dir; /* size of the central directory */
+ uLong offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info cur_file_info; /* public info about the current file in zip*/
+ unz_file_info_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+ int encrypted;
+# ifndef NOUNCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const unsigned long* pcrc_32_tab;
+# endif
+} unz_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+
+local int unzlocal_getByte OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream,
+ int *pi));
+
+local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ int *pi;
+{
+ unsigned char c;
+ int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return UNZ_OK;
+ }
+ else
+ {
+ if (ZERROR(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unzlocal_getShort OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong *pX;
+{
+ uLong x ;
+ int i;
+ int err;
+
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unzlocal_getLong OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong *pX;
+{
+ uLong x ;
+ int i;
+ int err;
+
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (fileName1,fileName2)
+ const char* fileName1;
+ const char* fileName2;
+{
+ for (;;)
+ {
+ char c1=*(fileName1++);
+ char c2=*(fileName2++);
+ if ((c1>='a') && (c1<='z'))
+ c1 -= 0x20;
+ if ((c2>='a') && (c2<='z'))
+ c2 -= 0x20;
+ if (c1=='\0')
+ return ((c2=='\0') ? 0 : -1);
+ if (c2=='\0')
+ return 1;
+ if (c1<c2)
+ return -1;
+ if (c1>c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
+ const char* fileName1;
+ const char* fileName2;
+ int iCaseSensitivity;
+{
+ if (iCaseSensitivity==0)
+ iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity==1)
+ return strcmp(fileName1,fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local uLong unzlocal_SearchCentralDir OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream));
+
+local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+{
+ unsigned char* buf;
+ uLong uSizeFile;
+ uLong uBackRead;
+ uLong uMaxBack=0xffff; /* maximum size of global comment */
+ uLong uPosFound=0;
+
+ if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize,uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+ if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+ "zlib/zlib114.zip".
+ If the zipfile cannot be opened (file doesn't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
+ const char *path;
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ unz_s us;
+ unz_s *s;
+ uLong central_pos,uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ uLong number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (unz_copyright[0]!=' ')
+ return NULL;
+
+ if (pzlib_filefunc_def==NULL)
+ fill_fopen_filefunc(&us.z_filefunc);
+ else
+ us.z_filefunc = *pzlib_filefunc_def;
+
+ us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+ ZLIB_FILEFUNC_MODE_EXISTING);
+ if (us.filestream==NULL)
+ return NULL;
+
+ central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
+ if (central_pos==0)
+ err=UNZ_ERRNO;
+
+ if (ZSEEK(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* zipfile comment length */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ ZCLOSE(us.z_filefunc, us.filestream);
+ return NULL;
+ }
+
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+
+ s=(unz_s*)ALLOC(sizeof(unz_s));
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen (path)
+ const char *path;
+{
+ return unzOpen2(path, NULL);
+}
+
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (file)
+ unzFile file;
+{
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ ZCLOSE(s->z_filefunc, s->filestream);
+ TRYFREE(s);
+ return UNZ_OK;
+}
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
+ unzFile file;
+ unz_global_info *pglobal_info;
+{
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+
+/*
+ Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
+ uLong ulDosDate;
+ tm_unz* ptm;
+{
+ uLong uDate;
+ uDate = (uLong)(ulDosDate>>16);
+ ptm->tm_mday = (uInt)(uDate&0x1f) ;
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+ Get Info about the current file in the zipfile, with internal only info
+*/
+local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
+ unz_file_info *pfile_info,
+ unz_file_info_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+local int unzlocal_GetCurrentFileInfoInternal (file,
+ pfile_info,
+ pfile_info_internal,
+ szFileName, fileNameBufferSize,
+ extraField, extraFieldBufferSize,
+ szComment, commentBufferSize)
+ unzFile file;
+ unz_file_info *pfile_info;
+ unz_file_info_internal *pfile_info_internal;
+ char *szFileName;
+ uLong fileNameBufferSize;
+ void *extraField;
+ uLong extraFieldBufferSize;
+ char *szComment;
+ uLong commentBufferSize;
+{
+ unz_s* s;
+ unz_file_info file_info;
+ unz_file_info_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (ZSEEK(s->z_filefunc, s->filestream,
+ s->pos_in_central_dir+s->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ {
+ err=UNZ_ERRNO;
+ }
+ else if (uMagic!=0x02014b50)
+ {
+ err=UNZ_BADZIPFILE;
+ }
+ }
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ lSeek+=file_info.size_filename;
+ if ((err==UNZ_OK) && (szFileName!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_filename<fileNameBufferSize)
+ {
+ *(szFileName+file_info.size_filename)='\0';
+ uSizeRead = file_info.size_filename;
+ }
+ else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+ if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+
+
+ if ((err==UNZ_OK) && (extraField!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_extra<extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ {
+ lSeek=0;
+ }
+ else
+ {
+ err=UNZ_ERRNO;
+ }
+ }
+ if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+ {
+ if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
+ {
+ err=UNZ_ERRNO;
+ }
+ }
+ lSeek += file_info.size_file_extra - uSizeRead;
+ }
+ else
+ {
+ lSeek+=file_info.size_file_extra;
+ }
+
+ if ((err==UNZ_OK) && (szComment!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_comment<commentBufferSize)
+ {
+ *(szComment+file_info.size_file_comment)='\0';
+ uSizeRead = file_info.size_file_comment;
+ }
+ else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ {
+ lSeek=0;
+ }
+ else
+ {
+ err=UNZ_ERRNO;
+ }
+ }
+ if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+ {
+ if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+ {
+ err=UNZ_ERRNO;
+ }
+ }
+ lSeek+=file_info.size_file_comment - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_comment;
+
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+ if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ *pfile_info_internal=file_info_internal;
+
+ return err;
+}
+
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo (file,
+ pfile_info,
+ szFileName, fileNameBufferSize,
+ extraField, extraFieldBufferSize,
+ szComment, commentBufferSize)
+ unzFile file;
+ unz_file_info *pfile_info;
+ char *szFileName;
+ uLong fileNameBufferSize;
+ void *extraField;
+ uLong extraFieldBufferSize;
+ char *szComment;
+ uLong commentBufferSize;
+{
+ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+}
+
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ s->pos_in_central_dir=s->offset_central_dir;
+ s->num_file=0;
+ err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (file)
+ unzFile file;
+{
+ unz_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
+ if (s->num_file+1==s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->num_file++;
+ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzipStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
+ unzFile file;
+ const char *szFileName;
+ int iCaseSensitivity;
+{
+ unz_s* s;
+ int err;
+
+ /* We remember the 'current' position in the file so that we can jump
+ * back there if we fail.
+ */
+ unz_file_info cur_file_infoSaved;
+ unz_file_info_internal cur_file_info_internalSaved;
+ uLong num_fileSaved;
+ uLong pos_in_central_dirSaved;
+
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+ if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+ return UNZ_PARAMERROR;
+
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ /* Save the current state */
+ num_fileSaved = s->num_file;
+ pos_in_central_dirSaved = s->pos_in_central_dir;
+ cur_file_infoSaved = s->cur_file_info;
+ cur_file_info_internalSaved = s->cur_file_info_internal;
+
+ err = unzGoToFirstFile(file);
+
+ while (err == UNZ_OK)
+ {
+ char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+ err = unzGetCurrentFileInfo(file,NULL,
+ szCurrentFileName,sizeof(szCurrentFileName)-1,
+ NULL,0,NULL,0);
+ if (err == UNZ_OK)
+ {
+ if (unzStringFileNameCompare(szCurrentFileName,
+ szFileName,iCaseSensitivity)==0)
+ return UNZ_OK;
+ err = unzGoToNextFile(file);
+ }
+ }
+
+ /* We failed, so restore the state of the 'current file' to where we
+ * were.
+ */
+ s->num_file = num_fileSaved ;
+ s->pos_in_central_dir = pos_in_central_dirSaved ;
+ s->cur_file_info = cur_file_infoSaved;
+ s->cur_file_info_internal = cur_file_info_internalSaved;
+ return err;
+}
+
+
+/*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+ uLong pos_in_zip_directory; // offset in file
+ uLong num_of_file; // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos(file, file_pos)
+ unzFile file;
+ unz_file_pos* file_pos;
+{
+ unz_s* s;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ file_pos->pos_in_zip_directory = s->pos_in_central_dir;
+ file_pos->num_of_file = s->num_file;
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGoToFilePos(file, file_pos)
+ unzFile file;
+ unz_file_pos* file_pos;
+{
+ unz_s* s;
+ int err;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ /* jump to the right spot */
+ s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+ s->num_file = file_pos->num_of_file;
+
+ /* set the current file */
+ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ /* return results */
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
+ Read the local header of the current zipfile
+ Check the coherency of the local header and info in the end of central
+ directory about this file
+ store in *piSizeVar the size of extra info in local header
+ (filename and size of extra field data)
+*/
+local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
+ poffset_local_extrafield,
+ psize_local_extrafield)
+ unz_s* s;
+ uInt* piSizeVar;
+ uLong *poffset_local_extrafield;
+ uInt *psize_local_extrafield;
+{
+ uLong uMagic,uData,uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err=UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+ s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+
+ if (err==UNZ_OK)
+ {
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ {
+ err=UNZ_ERRNO;
+ }
+ else if (uMagic!=0x04034b50)
+ {
+ err=UNZ_BADZIPFILE;
+ }
+ }
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+/*
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ err=UNZ_BADZIPFILE;
+*/
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+ err=UNZ_BADZIPFILE;
+
+ if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+ err=UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt)size_filename;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+ err=UNZ_ERRNO;
+ *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt)size_extra_field;
+
+ *piSizeVar += (uInt)size_extra_field;
+
+ return err;
+}
+
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
+ unzFile file;
+ int* method;
+ int* level;
+ int raw;
+ const char* password;
+{
+ int err=UNZ_OK;
+ uInt iSizeVar;
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ uLong offset_local_extrafield; /* offset of the local extra field */
+ uInt size_local_extrafield; /* size of the local extra field */
+# ifndef NOUNCRYPT
+ char source[12];
+# else
+ if (password != NULL)
+ return UNZ_PARAMERROR;
+# endif
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile(file);
+
+ if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+ &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+ ALLOC(sizeof(file_in_zip_read_info_s));
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield=0;
+ pfile_in_zip_read_info->raw=raw;
+
+ if (pfile_in_zip_read_info->read_buffer==NULL)
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+
+ pfile_in_zip_read_info->stream_initialised=0;
+
+ if (method!=NULL)
+ *method = (int)s->cur_file_info.compression_method;
+
+ if (level!=NULL)
+ {
+ *level = 6;
+ switch (s->cur_file_info.flag & 0x06)
+ {
+ case 6 : *level = 1; break;
+ case 4 : *level = 2; break;
+ case 2 : *level = 9; break;
+ }
+ }
+
+ if ((s->cur_file_info.compression_method!=0) &&
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32=0;
+ pfile_in_zip_read_info->compression_method =
+ s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->filestream=s->filestream;
+ pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+ pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
+ (!raw))
+ {
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=1;
+ else
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return err;
+ }
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END.
+ * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+ * size of both compressed and uncompressed data
+ */
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size ;
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+
+# ifndef NOUNCRYPT
+ if (password != NULL)
+ {
+ int i;
+ s->pcrc_32_tab = get_crc_table();
+ init_keys(password,s->keys,s->pcrc_32_tab);
+ if (ZSEEK(s->z_filefunc, s->filestream,
+ s->pfile_in_zip_read->pos_in_zipfile +
+ s->pfile_in_zip_read->byte_before_the_zipfile,
+ SEEK_SET)!=0)
+ return UNZ_INTERNALERROR;
+ if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
+ return UNZ_INTERNALERROR;
+
+ for (i = 0; i<12; i++)
+ zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+ s->pfile_in_zip_read->pos_in_zipfile+=12;
+ s->encrypted=1;
+ }
+# endif
+
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzOpenCurrentFile (file)
+ unzFile file;
+{
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
+ unzFile file;
+ const char* password;
+{
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
+ unzFile file;
+ int* method;
+ int* level;
+ int raw;
+{
+ return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
+
+/*
+ Read bytes from the current file.
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile (file, buf, len)
+ unzFile file;
+ voidp buf;
+ unsigned len;
+{
+ int err=UNZ_OK;
+ uInt iRead = 0;
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->read_buffer == NULL))
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+ if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+ (!(pfile_in_zip_read_info->raw)))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+ if ((len>pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in) &&
+ (pfile_in_zip_read_info->raw))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in;
+
+ while (pfile_in_zip_read_info->stream.avail_out>0)
+ {
+ if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+ (pfile_in_zip_read_info->rest_read_compressed>0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+ uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+ if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->read_buffer,
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+
+# ifndef NOUNCRYPT
+ if(s->encrypted)
+ {
+ uInt i;
+ for(i=0;i<uReadThis;i++)
+ pfile_in_zip_read_info->read_buffer[i] =
+ zdecode(s->keys,s->pcrc_32_tab,
+ pfile_in_zip_read_info->read_buffer[i]);
+ }
+# endif
+
+
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef*)pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+ }
+
+ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+ {
+ uInt uDoCopy,i ;
+
+ if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ return (iRead==0) ? UNZ_EOF : iRead;
+
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+ for (i=0;i<uDoCopy;i++)
+ *(pfile_in_zip_read_info->stream.next_out+i) =
+ *(pfile_in_zip_read_info->stream.next_in+i);
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ }
+ else
+ {
+ uLong uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+ int flush=Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ pfile_in_zip_read_info->stream.avail_out) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ flush = Z_FINISH;
+ */
+ err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+ if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+ err = Z_DATA_ERROR;
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32(pfile_in_zip_read_info->crc32,bufBefore,
+ (uInt)(uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ if (err==Z_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=Z_OK)
+ break;
+ }
+ }
+
+ if (err==Z_OK)
+ return iRead;
+ return err;
+}
+
+
+/*
+ Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (file)
+ unzFile file;
+{
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof (file)
+ unzFile file;
+{
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field that can be read
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
+ unzFile file;
+ voidp buf;
+ unsigned len;
+{
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ uInt read_now;
+ uLong size_to_read;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+ pfile_in_zip_read_info->pos_local_extrafield);
+
+ if (buf==NULL)
+ return (int)size_to_read;
+
+ if (len>size_to_read)
+ read_now = (uInt)size_to_read;
+ else
+ read_now = (uInt)len ;
+
+ if (read_now==0)
+ return 0;
+
+ if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->offset_local_extrafield +
+ pfile_in_zip_read_info->pos_local_extrafield,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ buf,read_now)!=read_now)
+ return UNZ_ERRNO;
+
+ return (int)read_now;
+}
+
+/*
+ Close the file in zip opened with unzipOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+ (!pfile_in_zip_read_info->raw))
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ err=UNZ_CRCERROR;
+ }
+
+
+ TRYFREE(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read=NULL;
+
+ return err;
+}
+
+
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
+ unzFile file;
+ char *szComment;
+ uLong uSizeBuf;
+{
+/* int err=UNZ_OK;*/
+ unz_s* s;
+ uLong uReadThis ;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ uReadThis = uSizeBuf;
+ if (uReadThis>s->gi.size_comment)
+ uReadThis = s->gi.size_comment;
+
+ if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (uReadThis>0)
+ {
+ *szComment='\0';
+ if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+ }
+
+ if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ *(szComment+s->gi.size_comment)='\0';
+ return (int)uReadThis;
+}
+
+/* Additions by RX '2004 */
+extern uLong ZEXPORT unzGetOffset (file)
+ unzFile file;
+{
+ unz_s* s;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return 0;
+ if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
+ if (s->num_file==s->gi.number_entry)
+ return 0;
+ return s->pos_in_central_dir;
+}
+
+extern int ZEXPORT unzSetOffset (file, pos)
+ unzFile file;
+ uLong pos;
+{
+ unz_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ s->pos_in_central_dir = pos;
+ s->num_file = s->gi.number_entry; /* hack */
+ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
diff --git a/ossimPlanet/src/ossimPlanet/zip.c b/ossimPlanet/src/ossimPlanet/zip.c
new file mode 100644
index 0000000..7eee2e8
--- /dev/null
+++ b/ossimPlanet/src/ossimPlanet/zip.c
@@ -0,0 +1,1219 @@
+/* zip.c -- IO on .zip files using zlib
+ Version 1.01e, February 12th, 2005
+
+ 27 Dec 2004 Rolf Kalbermatter
+ Modification to zipOpen2 to support globalComment retrieval.
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ Read zip.h for more info
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "zlib.h"
+#include <ossimPlanet/zip.h>
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#ifndef VERSIONMADEBY
+# define VERSIONMADEBY (0x0) /* platform depedent */
+#endif
+
+#ifndef Z_BUFSIZE
+#define Z_BUFSIZE (16384)
+#endif
+
+#ifndef Z_MAXFILENAMEINZIP
+#define Z_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+/*
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+*/
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef DEF_MEM_LEVEL
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+#endif
+const char zip_copyright[] =
+ " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+
+#define SIZEDATA_INDATABLOCK (4096-(4*4))
+
+#define LOCALHEADERMAGIC (0x04034b50)
+#define CENTRALHEADERMAGIC (0x02014b50)
+#define ENDHEADERMAGIC (0x06054b50)
+
+#define FLAG_LOCALHEADER_OFFSET (0x06)
+#define CRC_LOCALHEADER_OFFSET (0x0e)
+
+#define SIZECENTRALHEADER (0x2e) /* 46 */
+
+typedef struct linkedlist_datablock_internal_s
+{
+ struct linkedlist_datablock_internal_s* next_datablock;
+ uLong avail_in_this_block;
+ uLong filled_in_this_block;
+ uLong unused; /* for future use and alignement */
+ unsigned char data[SIZEDATA_INDATABLOCK];
+} linkedlist_datablock_internal;
+
+typedef struct linkedlist_data_s
+{
+ linkedlist_datablock_internal* first_block;
+ linkedlist_datablock_internal* last_block;
+} linkedlist_data;
+
+
+typedef struct
+{
+ z_stream stream; /* zLib stream structure for inflate */
+ int stream_initialised; /* 1 is stream is initialised */
+ uInt pos_in_buffered_data; /* last written byte in buffered_data */
+
+ uLong pos_local_header; /* offset of the local header of the file
+ currenty writing */
+ char* central_header; /* central header data for the current file */
+ uLong size_centralheader; /* size of the central header for cur file */
+ uLong flag; /* flag of the file currently writing */
+
+ int method; /* compression method of file currenty wr.*/
+ int raw; /* 1 for directly writing raw data */
+ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
+ uLong dosDate;
+ uLong crc32;
+ int encrypt;
+#ifndef NOCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const unsigned long* pcrc_32_tab;
+ int crypt_header_size;
+#endif
+} curfile_info;
+
+typedef struct
+{
+ zlib_filefunc_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ linkedlist_data central_dir;/* datablock with central dir in construction*/
+ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
+ curfile_info ci; /* info on the file curretly writing */
+
+ uLong begin_pos; /* position of the beginning of the zipfile */
+ uLong add_position_when_writting_offset;
+ uLong number_entry;
+#ifndef NO_ADDFILEINEXISTINGZIP
+ char *globalcomment;
+#endif
+} zip_internal;
+
+
+
+#ifndef NOCRYPT
+#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+#include "crypt.h"
+#endif
+
+local linkedlist_datablock_internal* allocate_new_datablock()
+{
+ linkedlist_datablock_internal* ldi;
+ ldi = (linkedlist_datablock_internal*)
+ ALLOC(sizeof(linkedlist_datablock_internal));
+ if (ldi!=NULL)
+ {
+ ldi->next_datablock = NULL ;
+ ldi->filled_in_this_block = 0 ;
+ ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
+ }
+ return ldi;
+}
+
+local void free_datablock(ldi)
+ linkedlist_datablock_internal* ldi;
+{
+ while (ldi!=NULL)
+ {
+ linkedlist_datablock_internal* ldinext = ldi->next_datablock;
+ TRYFREE(ldi);
+ ldi = ldinext;
+ }
+}
+
+local void init_linkedlist(ll)
+ linkedlist_data* ll;
+{
+ ll->first_block = ll->last_block = NULL;
+}
+
+local void free_linkedlist(ll)
+ linkedlist_data* ll;
+{
+ free_datablock(ll->first_block);
+ ll->first_block = ll->last_block = NULL;
+}
+
+
+local int add_data_in_datablock(ll,buf,len)
+ linkedlist_data* ll;
+ const void* buf;
+ uLong len;
+{
+ linkedlist_datablock_internal* ldi;
+ const unsigned char* from_copy;
+
+ if (ll==NULL)
+ return ZIP_INTERNALERROR;
+
+ if (ll->last_block == NULL)
+ {
+ ll->first_block = ll->last_block = allocate_new_datablock();
+ if (ll->first_block == NULL)
+ return ZIP_INTERNALERROR;
+ }
+
+ ldi = ll->last_block;
+ from_copy = (unsigned char*)buf;
+
+ while (len>0)
+ {
+ uInt copy_this;
+ uInt i;
+ unsigned char* to_copy;
+
+ if (ldi->avail_in_this_block==0)
+ {
+ ldi->next_datablock = allocate_new_datablock();
+ if (ldi->next_datablock == NULL)
+ return ZIP_INTERNALERROR;
+ ldi = ldi->next_datablock ;
+ ll->last_block = ldi;
+ }
+
+ if (ldi->avail_in_this_block < len)
+ copy_this = (uInt)ldi->avail_in_this_block;
+ else
+ copy_this = (uInt)len;
+
+ to_copy = &(ldi->data[ldi->filled_in_this_block]);
+
+ for (i=0;i<copy_this;i++)
+ *(to_copy+i)=*(from_copy+i);
+
+ ldi->filled_in_this_block += copy_this;
+ ldi->avail_in_this_block -= copy_this;
+ from_copy += copy_this ;
+ len -= copy_this;
+ }
+ return ZIP_OK;
+}
+
+
+
+/****************************************************************************/
+
+#ifndef NO_ADDFILEINEXISTINGZIP
+/* ===========================================================================
+ Inputs a long in LSB order to the given file
+ nbByte == 1, 2 or 4 (byte, short or long)
+*/
+
+local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream, uLong x, int nbByte));
+local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong x;
+ int nbByte;
+{
+ unsigned char buf[4];
+ int n;
+ for (n = 0; n < nbByte; n++)
+ {
+ buf[n] = (unsigned char)(x & 0xff);
+ x >>= 8;
+ }
+ if (x != 0)
+ { /* data overflow - hack for ZIP64 (X Roche) */
+ for (n = 0; n < nbByte; n++)
+ {
+ buf[n] = 0xff;
+ }
+ }
+
+ if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
+ return ZIP_ERRNO;
+ else
+ return ZIP_OK;
+}
+
+local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
+local void ziplocal_putValue_inmemory (dest, x, nbByte)
+ void* dest;
+ uLong x;
+ int nbByte;
+{
+ unsigned char* buf=(unsigned char*)dest;
+ int n;
+ for (n = 0; n < nbByte; n++) {
+ buf[n] = (unsigned char)(x & 0xff);
+ x >>= 8;
+ }
+
+ if (x != 0)
+ { /* data overflow - hack for ZIP64 */
+ for (n = 0; n < nbByte; n++)
+ {
+ buf[n] = 0xff;
+ }
+ }
+}
+
+/****************************************************************************/
+
+
+local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
+ const tm_zip* ptm;
+ uLong dosDate;
+{
+ uLong year = (uLong)ptm->tm_year;
+ if (year>1980)
+ year-=1980;
+ else if (year>80)
+ year-=80;
+ return
+ (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
+ ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
+}
+
+
+/****************************************************************************/
+
+local int ziplocal_getByte OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream,
+ int *pi));
+
+local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ int *pi;
+{
+ unsigned char c;
+ int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return ZIP_OK;
+ }
+ else
+ {
+ if (ZERROR(*pzlib_filefunc_def,filestream))
+ return ZIP_ERRNO;
+ else
+ return ZIP_EOF;
+ }
+}
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int ziplocal_getShort OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong *pX;
+{
+ uLong x ;
+ int i;
+ int err;
+
+ err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==ZIP_OK)
+ err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==ZIP_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int ziplocal_getLong OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong *pX;
+{
+ uLong x ;
+ int i;
+ int err;
+
+ err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==ZIP_OK)
+ err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==ZIP_OK)
+ err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<16;
+
+ if (err==ZIP_OK)
+ err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==ZIP_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local uLong ziplocal_SearchCentralDir OF((
+ const zlib_filefunc_def* pzlib_filefunc_def,
+ voidpf filestream));
+
+local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+{
+ unsigned char* buf;
+ uLong uSizeFile;
+ uLong uBackRead;
+ uLong uMaxBack=0xffff; /* maximum size of global comment */
+ uLong uPosFound=0;
+
+ if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize,uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+ if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+#endif /* !NO_ADDFILEINEXISTINGZIP*/
+
+/************************************************************/
+extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
+ const char *pathname;
+ int append;
+ zipcharpc* globalcomment;
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ zip_internal ziinit;
+ zip_internal* zi;
+ int err=ZIP_OK;
+
+
+ if (pzlib_filefunc_def==NULL)
+ fill_fopen_filefunc(&ziinit.z_filefunc);
+ else
+ ziinit.z_filefunc = *pzlib_filefunc_def;
+
+ ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
+ (ziinit.z_filefunc.opaque,
+ pathname,
+ (append == APPEND_STATUS_CREATE) ?
+ (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
+ (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
+
+ if (ziinit.filestream == NULL)
+ return NULL;
+ ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
+ ziinit.in_opened_file_inzip = 0;
+ ziinit.ci.stream_initialised = 0;
+ ziinit.number_entry = 0;
+ ziinit.add_position_when_writting_offset = 0;
+ init_linkedlist(&(ziinit.central_dir));
+
+
+ zi = (zip_internal*)ALLOC(sizeof(zip_internal));
+ if (zi==NULL)
+ {
+ ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
+ return NULL;
+ }
+
+ /* now we add file in a zipfile */
+# ifndef NO_ADDFILEINEXISTINGZIP
+ ziinit.globalcomment = NULL;
+ if (append == APPEND_STATUS_ADDINZIP)
+ {
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+
+ uLong size_central_dir; /* size of the central directory */
+ uLong offset_central_dir; /* offset of start of central directory */
+ uLong central_pos,uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ uLong number_entry;
+ uLong number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+ uLong size_comment;
+
+ central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
+ if (central_pos==0)
+ err=ZIP_ERRNO;
+
+ if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=ZIP_ERRNO;
+
+ /* the signature, already checked */
+ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ /* number of this disk */
+ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ /* total number of entries in the central dir */
+ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ if ((number_entry_CD!=number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=ZIP_BADZIPFILE;
+
+ /* size of the central directory */
+ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ /* zipfile global comment length */
+ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
+ err=ZIP_ERRNO;
+
+ if ((central_pos<offset_central_dir+size_central_dir) &&
+ (err==ZIP_OK))
+ err=ZIP_BADZIPFILE;
+
+ if (err!=ZIP_OK)
+ {
+ ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
+ return NULL;
+ }
+
+ if (size_comment>0)
+ {
+ ziinit.globalcomment = ALLOC(size_comment+1);
+ if (ziinit.globalcomment)
+ {
+ size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
+ ziinit.globalcomment[size_comment]=0;
+ }
+ }
+
+ byte_before_the_zipfile = central_pos -
+ (offset_central_dir+size_central_dir);
+ ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
+
+ {
+ uLong size_central_dir_to_read = size_central_dir;
+ size_t buf_size = SIZEDATA_INDATABLOCK;
+ void* buf_read = (void*)ALLOC(buf_size);
+ if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+ offset_central_dir + byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET) != 0)
+ err=ZIP_ERRNO;
+
+ while ((size_central_dir_to_read>0) && (err==ZIP_OK))
+ {
+ uLong read_this = SIZEDATA_INDATABLOCK;
+ if (read_this > size_central_dir_to_read)
+ read_this = size_central_dir_to_read;
+ if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
+ err=ZIP_ERRNO;
+
+ if (err==ZIP_OK)
+ err = add_data_in_datablock(&ziinit.central_dir,buf_read,
+ (uLong)read_this);
+ size_central_dir_to_read-=read_this;
+ }
+ TRYFREE(buf_read);
+ }
+ ziinit.begin_pos = byte_before_the_zipfile;
+ ziinit.number_entry = number_entry_CD;
+
+ if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+ offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=ZIP_ERRNO;
+ }
+
+ if (globalcomment)
+ {
+ *globalcomment = ziinit.globalcomment;
+ }
+# endif /* !NO_ADDFILEINEXISTINGZIP*/
+
+ if (err != ZIP_OK)
+ {
+# ifndef NO_ADDFILEINEXISTINGZIP
+ TRYFREE(ziinit.globalcomment);
+# endif /* !NO_ADDFILEINEXISTINGZIP*/
+ TRYFREE(zi);
+ return NULL;
+ }
+ else
+ {
+ *zi = ziinit;
+ return (zipFile)zi;
+ }
+}
+
+extern zipFile ZEXPORT zipOpen (pathname, append)
+ const char *pathname;
+ int append;
+{
+ return zipOpen2(pathname,append,NULL,NULL);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
+ extrafield_local, size_extrafield_local,
+ extrafield_global, size_extrafield_global,
+ comment, method, level, raw,
+ windowBits, memLevel, strategy,
+ password, crcForCrypting)
+ zipFile file;
+ const char* filename;
+ const zip_fileinfo* zipfi;
+ const void* extrafield_local;
+ uInt size_extrafield_local;
+ const void* extrafield_global;
+ uInt size_extrafield_global;
+ const char* comment;
+ int method;
+ int level;
+ int raw;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char* password;
+ uLong crcForCrypting;
+{
+ zip_internal* zi;
+ uInt size_filename;
+ uInt size_comment;
+ uInt i;
+ int err = ZIP_OK;
+
+# ifdef NOCRYPT
+ if (password != NULL)
+ return ZIP_PARAMERROR;
+# endif
+
+ if (file == NULL)
+ return ZIP_PARAMERROR;
+ if ((method!=0) && (method!=Z_DEFLATED))
+ return ZIP_PARAMERROR;
+
+ zi = (zip_internal*)file;
+
+ if (zi->in_opened_file_inzip == 1)
+ {
+ err = zipCloseFileInZip (file);
+ if (err != ZIP_OK)
+ return err;
+ }
+
+
+ if (filename==NULL)
+ filename="-";
+
+ if (comment==NULL)
+ size_comment = 0;
+ else
+ size_comment = (uInt)strlen(comment);
+
+ size_filename = (uInt)strlen(filename);
+
+ if (zipfi == NULL)
+ zi->ci.dosDate = 0;
+ else
+ {
+ if (zipfi->dosDate != 0)
+ zi->ci.dosDate = zipfi->dosDate;
+ else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
+ }
+
+ zi->ci.flag = 0;
+ if ((level==8) || (level==9))
+ zi->ci.flag |= 2;
+ if ((level==2))
+ zi->ci.flag |= 4;
+ if ((level==1))
+ zi->ci.flag |= 6;
+ if (password != NULL)
+ zi->ci.flag |= 1;
+
+ zi->ci.crc32 = 0;
+ zi->ci.method = method;
+ zi->ci.encrypt = 0;
+ zi->ci.stream_initialised = 0;
+ zi->ci.pos_in_buffered_data = 0;
+ zi->ci.raw = raw;
+ zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
+ zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
+ size_extrafield_global + size_comment;
+ zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
+
+ ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
+ /* version info */
+ ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
+ ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
+ ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
+ ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
+ ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
+
+ if (zipfi==NULL)
+ ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
+ else
+ ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
+
+ if (zipfi==NULL)
+ ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
+ else
+ ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
+
+ ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
+
+ for (i=0;i<size_filename;i++)
+ *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
+
+ for (i=0;i<size_extrafield_global;i++)
+ *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
+ *(((const char*)extrafield_global)+i);
+
+ for (i=0;i<size_comment;i++)
+ *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
+ size_extrafield_global+i) = *(comment+i);
+ if (zi->ci.central_header == NULL)
+ return ZIP_INTERNALERROR;
+
+ /* write the local header */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
+
+ if ((err==ZIP_OK) && (size_filename>0))
+ if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
+ err = ZIP_ERRNO;
+
+ if ((err==ZIP_OK) && (size_extrafield_local>0))
+ if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
+ !=size_extrafield_local)
+ err = ZIP_ERRNO;
+
+ zi->ci.stream.avail_in = (uInt)0;
+ zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+ zi->ci.stream.next_out = zi->ci.buffered_data;
+ zi->ci.stream.total_in = 0;
+ zi->ci.stream.total_out = 0;
+
+ if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+ {
+ zi->ci.stream.zalloc = (alloc_func)0;
+ zi->ci.stream.zfree = (free_func)0;
+ zi->ci.stream.opaque = (voidpf)0;
+
+ if (windowBits>0)
+ windowBits = -windowBits;
+
+ err = deflateInit2(&zi->ci.stream, level,
+ Z_DEFLATED, windowBits, memLevel, strategy);
+
+ if (err==Z_OK)
+ zi->ci.stream_initialised = 1;
+ }
+# ifndef NOCRYPT
+ zi->ci.crypt_header_size = 0;
+ if ((err==Z_OK) && (password != NULL))
+ {
+ unsigned char bufHead[RAND_HEAD_LEN];
+ unsigned int sizeHead;
+ zi->ci.encrypt = 1;
+ zi->ci.pcrc_32_tab = get_crc_table();
+ /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
+
+ sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
+ zi->ci.crypt_header_size = sizeHead;
+
+ if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
+ err = ZIP_ERRNO;
+ }
+# endif
+
+ if (err==Z_OK)
+ zi->in_opened_file_inzip = 1;
+ return err;
+}
+
+extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
+ extrafield_local, size_extrafield_local,
+ extrafield_global, size_extrafield_global,
+ comment, method, level, raw)
+ zipFile file;
+ const char* filename;
+ const zip_fileinfo* zipfi;
+ const void* extrafield_local;
+ uInt size_extrafield_local;
+ const void* extrafield_global;
+ uInt size_extrafield_global;
+ const char* comment;
+ int method;
+ int level;
+ int raw;
+{
+ return zipOpenNewFileInZip3 (file, filename, zipfi,
+ extrafield_local, size_extrafield_local,
+ extrafield_global, size_extrafield_global,
+ comment, method, level, raw,
+ -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+ NULL, 0);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
+ extrafield_local, size_extrafield_local,
+ extrafield_global, size_extrafield_global,
+ comment, method, level)
+ zipFile file;
+ const char* filename;
+ const zip_fileinfo* zipfi;
+ const void* extrafield_local;
+ uInt size_extrafield_local;
+ const void* extrafield_global;
+ uInt size_extrafield_global;
+ const char* comment;
+ int method;
+ int level;
+{
+ return zipOpenNewFileInZip2 (file, filename, zipfi,
+ extrafield_local, size_extrafield_local,
+ extrafield_global, size_extrafield_global,
+ comment, method, level, 0);
+}
+
+local int zipFlushWriteBuffer(zi)
+ zip_internal* zi;
+{
+ int err=ZIP_OK;
+
+ if (zi->ci.encrypt != 0)
+ {
+#ifndef NOCRYPT
+ uInt i;
+ int t;
+ for (i=0;i<zi->ci.pos_in_buffered_data;i++)
+ zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
+ zi->ci.buffered_data[i],t);
+#endif
+ }
+ if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
+ !=zi->ci.pos_in_buffered_data)
+ err = ZIP_ERRNO;
+ zi->ci.pos_in_buffered_data = 0;
+ return err;
+}
+
+extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
+ zipFile file;
+ const void* buf;
+ unsigned len;
+{
+ zip_internal* zi;
+ int err=ZIP_OK;
+
+ if (file == NULL)
+ return ZIP_PARAMERROR;
+ zi = (zip_internal*)file;
+
+ if (zi->in_opened_file_inzip == 0)
+ return ZIP_PARAMERROR;
+
+ zi->ci.stream.next_in = (void*)buf;
+ zi->ci.stream.avail_in = len;
+ zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
+
+ while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
+ {
+ if (zi->ci.stream.avail_out == 0)
+ {
+ if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
+ err = ZIP_ERRNO;
+ zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+ zi->ci.stream.next_out = zi->ci.buffered_data;
+ }
+
+
+ if(err != ZIP_OK)
+ break;
+
+ if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+ {
+ uLong uTotalOutBefore = zi->ci.stream.total_out;
+ err=deflate(&zi->ci.stream, Z_NO_FLUSH);
+ zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+
+ }
+ else
+ {
+ uInt copy_this,i;
+ if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
+ copy_this = zi->ci.stream.avail_in;
+ else
+ copy_this = zi->ci.stream.avail_out;
+ for (i=0;i<copy_this;i++)
+ *(((char*)zi->ci.stream.next_out)+i) =
+ *(((const char*)zi->ci.stream.next_in)+i);
+ {
+ zi->ci.stream.avail_in -= copy_this;
+ zi->ci.stream.avail_out-= copy_this;
+ zi->ci.stream.next_in+= copy_this;
+ zi->ci.stream.next_out+= copy_this;
+ zi->ci.stream.total_in+= copy_this;
+ zi->ci.stream.total_out+= copy_this;
+ zi->ci.pos_in_buffered_data += copy_this;
+ }
+ }
+ }
+
+ return err;
+}
+
+extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
+ zipFile file;
+ uLong uncompressed_size;
+ uLong crc32;
+{
+ zip_internal* zi;
+ uLong compressed_size;
+ int err=ZIP_OK;
+
+ if (file == NULL)
+ return ZIP_PARAMERROR;
+ zi = (zip_internal*)file;
+
+ if (zi->in_opened_file_inzip == 0)
+ return ZIP_PARAMERROR;
+ zi->ci.stream.avail_in = 0;
+
+ if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+ while (err==ZIP_OK)
+ {
+ uLong uTotalOutBefore;
+ if (zi->ci.stream.avail_out == 0)
+ {
+ if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
+ err = ZIP_ERRNO;
+ zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+ zi->ci.stream.next_out = zi->ci.buffered_data;
+ }
+ uTotalOutBefore = zi->ci.stream.total_out;
+ err=deflate(&zi->ci.stream, Z_FINISH);
+ zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+ }
+
+ if (err==Z_STREAM_END)
+ err=ZIP_OK; /* this is normal */
+
+ if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
+ if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
+ err = ZIP_ERRNO;
+
+ if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+ {
+ err=deflateEnd(&zi->ci.stream);
+ zi->ci.stream_initialised = 0;
+ }
+
+ if (!zi->ci.raw)
+ {
+ crc32 = (uLong)zi->ci.crc32;
+ uncompressed_size = (uLong)zi->ci.stream.total_in;
+ }
+ compressed_size = (uLong)zi->ci.stream.total_out;
+# ifndef NOCRYPT
+ compressed_size += zi->ci.crypt_header_size;
+# endif
+
+ ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
+ ziplocal_putValue_inmemory(zi->ci.central_header+20,
+ compressed_size,4); /*compr size*/
+ if (zi->ci.stream.data_type == Z_ASCII)
+ ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
+ ziplocal_putValue_inmemory(zi->ci.central_header+24,
+ uncompressed_size,4); /*uncompr size*/
+
+ if (err==ZIP_OK)
+ err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
+ (uLong)zi->ci.size_centralheader);
+ free(zi->ci.central_header);
+
+ if (err==ZIP_OK)
+ {
+ long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
+ if (ZSEEK(zi->z_filefunc,zi->filestream,
+ zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err = ZIP_ERRNO;
+
+ if (err==ZIP_OK)
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
+
+ if (err==ZIP_OK) /* compressed size, unknown */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
+
+ if (err==ZIP_OK) /* uncompressed size, unknown */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
+
+ if (ZSEEK(zi->z_filefunc,zi->filestream,
+ cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err = ZIP_ERRNO;
+ }
+
+ zi->number_entry ++;
+ zi->in_opened_file_inzip = 0;
+
+ return err;
+}
+
+extern int ZEXPORT zipCloseFileInZip (file)
+ zipFile file;
+{
+ return zipCloseFileInZipRaw (file,0,0);
+}
+
+extern int ZEXPORT zipClose (file, global_comment)
+ zipFile file;
+ const char* global_comment;
+{
+ zip_internal* zi;
+ int err = 0;
+ uLong size_centraldir = 0;
+ uLong centraldir_pos_inzip;
+ uInt size_global_comment;
+ if (file == NULL)
+ return ZIP_PARAMERROR;
+ zi = (zip_internal*)file;
+
+ if (zi->in_opened_file_inzip == 1)
+ {
+ err = zipCloseFileInZip (file);
+ }
+
+#ifndef NO_ADDFILEINEXISTINGZIP
+ if (global_comment==NULL)
+ global_comment = zi->globalcomment;
+#endif
+ if (global_comment==NULL)
+ size_global_comment = 0;
+ else
+ size_global_comment = (uInt)strlen(global_comment);
+
+ centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
+ if (err==ZIP_OK)
+ {
+ linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
+ while (ldi!=NULL)
+ {
+ if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
+ if (ZWRITE(zi->z_filefunc,zi->filestream,
+ ldi->data,ldi->filled_in_this_block)
+ !=ldi->filled_in_this_block )
+ err = ZIP_ERRNO;
+
+ size_centraldir += ldi->filled_in_this_block;
+ ldi = ldi->next_datablock;
+ }
+ }
+ free_datablock(zi->central_dir.first_block);
+
+ if (err==ZIP_OK) /* Magic End */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
+
+ if (err==ZIP_OK) /* number of this disk */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
+
+ if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
+
+ if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+
+ if (err==ZIP_OK) /* total number of entries in the central dir */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+
+ if (err==ZIP_OK) /* size of the central directory */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
+
+ if (err==ZIP_OK) /* offset of start of central directory with respect to the
+ starting disk number */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
+ (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+
+ if (err==ZIP_OK) /* zipfile comment length */
+ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
+
+ if ((err==ZIP_OK) && (size_global_comment>0))
+ if (ZWRITE(zi->z_filefunc,zi->filestream,
+ global_comment,size_global_comment) != size_global_comment)
+ err = ZIP_ERRNO;
+
+ if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
+ if (err == ZIP_OK)
+ err = ZIP_ERRNO;
+
+#ifndef NO_ADDFILEINEXISTINGZIP
+ TRYFREE(zi->globalcomment);
+#endif
+ TRYFREE(zi);
+
+ return err;
+}
diff --git a/ossimPlanet/xcode/ossimPlanet/English.lproj/InfoPlist.strings b/ossimPlanet/xcode/ossimPlanet/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..ce87cdb
Binary files /dev/null and b/ossimPlanet/xcode/ossimPlanet/English.lproj/InfoPlist.strings differ
diff --git a/ossimPlanet/xcode/ossimPlanet/Info.plist b/ossimPlanet/xcode/ossimPlanet/Info.plist
new file mode 100644
index 0000000..bd3e928
--- /dev/null
+++ b/ossimPlanet/xcode/ossimPlanet/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>ossimPlanet</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.carbonframeworktemplate</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+</dict>
+</plist>
diff --git a/ossimPlanet/xcode/ossimPlanet/ossimPlanet.xcodeproj/project.pbxproj b/ossimPlanet/xcode/ossimPlanet/ossimPlanet.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..7109bf4
--- /dev/null
+++ b/ossimPlanet/xcode/ossimPlanet/ossimPlanet.xcodeproj/project.pbxproj
@@ -0,0 +1,3219 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ EE9D26590DD888FB005A8951 /* All */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = EE9D26650DD88940005A8951 /* Build configuration list for PBXAggregateTarget "All" */;
+ buildPhases = (
+ );
+ dependencies = (
+ EE9D26610DD8891C005A8951 /* PBXTargetDependency */,
+ 43DFCC080FF0F4E000FB2061 /* PBXTargetDependency */,
+ 43DFCC0A0FF0F4E000FB2061 /* PBXTargetDependency */,
+ );
+ name = All;
+ productName = All;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 186EF5700B1CE22D00F7886A /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF4F60B1CE11D00F7886A /* ossim.framework */; };
+ 430485FE0F3CB80800B9C1E2 /* ossimPlanetDatabasePager.h in Headers */ = {isa = PBXBuildFile; fileRef = 430485FD0F3CB80800B9C1E2 /* ossimPlanetDatabasePager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4306ABAB10FE11A700C7202A /* osg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAA10FE11A700C7202A /* osg.framework */; };
+ 4306ABAD10FE11AC00C7202A /* osgGA.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAC10FE11AC00C7202A /* osgGA.framework */; };
+ 4306ABB210FE11C000C7202A /* osgDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAE10FE11C000C7202A /* osgDB.framework */; };
+ 4306ABB310FE11C000C7202A /* osgText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAF10FE11C000C7202A /* osgText.framework */; };
+ 4306ABB410FE11C000C7202A /* osgUtil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABB010FE11C000C7202A /* osgUtil.framework */; };
+ 4306ABB510FE11C000C7202A /* osgViewer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABB110FE11C000C7202A /* osgViewer.framework */; };
+ 430C8F670CBBD0B9002BAF12 /* ossimPlanetCompass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430C8F660CBBD0B8002BAF12 /* ossimPlanetCompass.cpp */; };
+ 430C8F690CBBD0CA002BAF12 /* ossimPlanetCompass.h in Headers */ = {isa = PBXBuildFile; fileRef = 430C8F680CBBD0CA002BAF12 /* ossimPlanetCompass.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 430D8E911100DA3F00EB0F96 /* ossimPlanetDepthPartitionNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 430D8E901100DA3F00EB0F96 /* ossimPlanetDepthPartitionNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 430D8E941100DA5200EB0F96 /* ossimPlanetDistanceAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 430D8E931100DA5200EB0F96 /* ossimPlanetDistanceAccumulator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 430D8E991100DB1F00EB0F96 /* ossimPlanetDepthPartitionNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D8E971100DB1F00EB0F96 /* ossimPlanetDepthPartitionNode.cpp */; };
+ 430D8E9A1100DB1F00EB0F96 /* ossimPlanetDistanceAccumulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D8E981100DB1F00EB0F96 /* ossimPlanetDistanceAccumulator.cpp */; };
+ 4314728F0CBE9F0F00EAADAB /* ossimPlanetVisitors.h in Headers */ = {isa = PBXBuildFile; fileRef = 4314728E0CBE9F0F00EAADAB /* ossimPlanetVisitors.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 431476550CA838310090B3CE /* ossimPlanetKmlScreenOverlayNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 431476540CA838310090B3CE /* ossimPlanetKmlScreenOverlayNode.cpp */; };
+ 431476570CA838400090B3CE /* ossimPlanetKmlScreenOverlayNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 431476560CA838400090B3CE /* ossimPlanetKmlScreenOverlayNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BE0F0C9717B400D36F21 /* ossimPlanetDtedElevationDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDBF0C9717B400D36F21 /* ossimPlanetDtedElevationDatabase.cpp */; };
+ 4315BE110C9717B400D36F21 /* ossimPlanetCubeGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC10C9717B400D36F21 /* ossimPlanetCubeGrid.cpp */; };
+ 4315BE120C9717B400D36F21 /* ossimPlanetWmsImageLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC20C9717B400D36F21 /* ossimPlanetWmsImageLayer.cpp */; };
+ 4315BE130C9717B400D36F21 /* ossimPlanetUtility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC30C9717B400D36F21 /* ossimPlanetUtility.cpp */; };
+ 4315BE140C9717B400D36F21 /* ossimPlanetThreadPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC40C9717B400D36F21 /* ossimPlanetThreadPool.cpp */; };
+ 4315BE150C9717B400D36F21 /* ossimPlanetThreadImp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC50C9717B400D36F21 /* ossimPlanetThreadImp.cpp */; };
+ 4315BE160C9717B400D36F21 /* ossimPlanetThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC60C9717B400D36F21 /* ossimPlanetThread.cpp */; };
+ 4315BE170C9717B400D36F21 /* ossimPlanetTextureLayerRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC70C9717B400D36F21 /* ossimPlanetTextureLayerRegistry.cpp */; };
+ 4315BE180C9717B400D36F21 /* ossimPlanetTextureLayerGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC80C9717B400D36F21 /* ossimPlanetTextureLayerGroup.cpp */; };
+ 4315BE190C9717B400D36F21 /* ossimPlanetTextureLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDC90C9717B400D36F21 /* ossimPlanetTextureLayer.cpp */; };
+ 4315BE1A0C9717B400D36F21 /* ossimPlanetStandardTextureLayerFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDCA0C9717B400D36F21 /* ossimPlanetStandardTextureLayerFactory.cpp */; };
+ 4315BE1B0C9717B400D36F21 /* ossimPlanetSocketNetworkConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDCB0C9717B400D36F21 /* ossimPlanetSocketNetworkConnection.cpp */; };
+ 4315BE1C0C9717B400D36F21 /* ossimPlanetShaderProgramSetup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDCC0C9717B400D36F21 /* ossimPlanetShaderProgramSetup.cpp */; };
+ 4315BE1D0C9717B400D36F21 /* ossimPlanetServerThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDCD0C9717B400D36F21 /* ossimPlanetServerThread.cpp */; };
+ 4315BE1E0C9717B400D36F21 /* ossimPlanetSceneView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDCE0C9717B400D36F21 /* ossimPlanetSceneView.cpp */; };
+ 4315BE1F0C9717B400D36F21 /* ossimPlanetPlaneGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDCF0C9717B400D36F21 /* ossimPlanetPlaneGrid.cpp */; };
+ 4315BE200C9717B400D36F21 /* ossimPlanetPagedLandLod.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD00C9717B400D36F21 /* ossimPlanetPagedLandLod.cpp */; };
+ 4315BE210C9717B400D36F21 /* ossimPlanetOssimImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD10C9717B400D36F21 /* ossimPlanetOssimImage.cpp */; };
+ 4315BE220C9717B400D36F21 /* ossimPlanetManipulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD20C9717B400D36F21 /* ossimPlanetManipulator.cpp */; };
+ 4315BE230C9717B400D36F21 /* ossimPlanetNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD30C9717B400D36F21 /* ossimPlanetNavigator.cpp */; };
+ 4315BE250C9717B400D36F21 /* ossimPlanetLookAt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD50C9717B400D36F21 /* ossimPlanetLookAt.cpp */; };
+ 4315BE260C9717B400D36F21 /* ossimPlanetLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD60C9717B400D36F21 /* ossimPlanetLayer.cpp */; };
+ 4315BE270C9717B400D36F21 /* ossimPlanetLatLonHud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD70C9717B400D36F21 /* ossimPlanetLatLonHud.cpp */; };
+ 4315BE280C9717B400D36F21 /* ulError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD80C9717B400D36F21 /* ulError.cpp */; };
+ 4315BE290C9717B400D36F21 /* ulClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDD90C9717B400D36F21 /* ulClock.cpp */; };
+ 4315BE2A0C9717B400D36F21 /* sg_socket_udp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDDA0C9717B400D36F21 /* sg_socket_udp.cpp */; };
+ 4315BE2B0C9717B400D36F21 /* ossimPlanetYahooGeocoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDDB0C9717B400D36F21 /* ossimPlanetYahooGeocoder.cpp */; };
+ 4315BE2C0C9717B400D36F21 /* ossimPlanetWmsClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDDC0C9717B400D36F21 /* ossimPlanetWmsClient.cpp */; };
+ 4315BE2D0C9717B400D36F21 /* ossimPlanetIoThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDDD0C9717B400D36F21 /* ossimPlanetIoThread.cpp */; };
+ 4315BE2E0C9717B400D36F21 /* ossimPlanetIoSocketServerChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDDE0C9717B400D36F21 /* ossimPlanetIoSocketServerChannel.cpp */; };
+ 4315BE2F0C9717B400D36F21 /* ossimPlanetIoSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDDF0C9717B400D36F21 /* ossimPlanetIoSocket.cpp */; };
+ 4315BE300C9717B400D36F21 /* ossimPlanetIoRoutableMessageHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE00C9717B400D36F21 /* ossimPlanetIoRoutableMessageHandler.cpp */; };
+ 4315BE310C9717B400D36F21 /* ossimPlanetInteractionController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE10C9717B400D36F21 /* ossimPlanetInteractionController.cpp */; };
+ 4315BE320C9717B400D36F21 /* ossimPlanetImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE20C9717B400D36F21 /* ossimPlanetImage.cpp */; };
+ 4315BE330C9717B400D36F21 /* ossimPlanetIdManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE30C9717B400D36F21 /* ossimPlanetIdManager.cpp */; };
+ 4315BE340C9717B400D36F21 /* ossimPlanetClientThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE40C9717B400D36F21 /* ossimPlanetClientThread.cpp */; };
+ 4315BE350C9717B400D36F21 /* ossimPlanetBoundingBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE50C9717B400D36F21 /* ossimPlanetBoundingBox.cpp */; };
+ 4315BE360C9717B400D36F21 /* ossimPlanetBillboardIcon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE60C9717B400D36F21 /* ossimPlanetBillboardIcon.cpp */; };
+ 4315BE370C9717B400D36F21 /* ossimPlanetKmlLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE70C9717B400D36F21 /* ossimPlanetKmlLayer.cpp */; };
+ 4315BE390C9717B400D36F21 /* ossimPlanetKml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDE90C9717B400D36F21 /* ossimPlanetKml.cpp */; };
+ 4315BE3A0C9717B400D36F21 /* ossimPlanetJpegImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDEA0C9717B400D36F21 /* ossimPlanetJpegImage.cpp */; };
+ 4315BE3B0C9717B400D36F21 /* ossimPlanet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDEB0C9717B400D36F21 /* ossimPlanet.cpp */; };
+ 4315BE3C0C9717B400D36F21 /* netSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDEC0C9717B400D36F21 /* netSocket.cpp */; };
+ 4315BE3D0C9717B400D36F21 /* netMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDED0C9717B400D36F21 /* netMonitor.cpp */; };
+ 4315BE3E0C9717B400D36F21 /* netMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDEE0C9717B400D36F21 /* netMessage.cpp */; };
+ 4315BE3F0C9717B400D36F21 /* netChat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDEF0C9717B400D36F21 /* netChat.cpp */; };
+ 4315BE400C9717B400D36F21 /* netChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF00C9717B400D36F21 /* netChannel.cpp */; };
+ 4315BE410C9717B400D36F21 /* netBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF10C9717B400D36F21 /* netBuffer.cpp */; };
+ 4315BE420C9717B400D36F21 /* mkUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF20C9717B400D36F21 /* mkUtils.cpp */; };
+ 4315BE430C9717B400D36F21 /* iochannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF30C9717B400D36F21 /* iochannel.cpp */; };
+ 4315BE440C9717B400D36F21 /* ossimPlanetGeocoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF40C9717B400D36F21 /* ossimPlanetGeocoder.cpp */; };
+ 4315BE460C9717B400D36F21 /* ossimPlanetActionRouter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF60C9717B400D36F21 /* ossimPlanetActionRouter.cpp */; };
+ 4315BE470C9717B400D36F21 /* ossimPlanetActionReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF70C9717B400D36F21 /* ossimPlanetActionReceiver.cpp */; };
+ 4315BE480C9717B400D36F21 /* ossimPlanetAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF80C9717B400D36F21 /* ossimPlanetAction.cpp */; };
+ 4315BE490C9717B400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDF90C9717B400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.cpp */; };
+ 4315BE4A0C9717B400D36F21 /* ossimPlanetElevationGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDFA0C9717B400D36F21 /* ossimPlanetElevationGrid.cpp */; };
+ 4315BE4B0C9717B400D36F21 /* ulLinkedList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDFB0C9717B400D36F21 /* ulLinkedList.cpp */; };
+ 4315BE4C0C9717B400D36F21 /* ossimPlanetLandCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDFC0C9717B400D36F21 /* ossimPlanetLandCache.cpp */; };
+ 4315BE4D0C9717B400D36F21 /* ossimPlanetLand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDFD0C9717B400D36F21 /* ossimPlanetLand.cpp */; };
+ 4315BE4E0C9717B400D36F21 /* ossimPlanetKmlLayerNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDFE0C9717B400D36F21 /* ossimPlanetKmlLayerNode.cpp */; };
+ 4315BE4F0C9717B400D36F21 /* sg_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BDFF0C9717B400D36F21 /* sg_file.cpp */; };
+ 4315BE500C9717B400D36F21 /* ossimPlanetTexture2D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE000C9717B400D36F21 /* ossimPlanetTexture2D.cpp */; };
+ 4315BE510C9717B400D36F21 /* ossimPlanetSrtmElevationDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE010C9717B400D36F21 /* ossimPlanetSrtmElevationDatabase.cpp */; };
+ 4315BE520C9717B400D36F21 /* ossimPlanetId.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE020C9717B400D36F21 /* ossimPlanetId.cpp */; };
+ 4315BE530C9717B400D36F21 /* ossimPlanetIconGeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE030C9717B400D36F21 /* ossimPlanetIconGeom.cpp */; };
+ 4315BE550C9717B400D36F21 /* ossimPlanetGridUtility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE050C9717B400D36F21 /* ossimPlanetGridUtility.cpp */; };
+ 4315BE560C9717B400D36F21 /* ulRTTI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE060C9717B400D36F21 /* ulRTTI.cpp */; };
+ 4315BE570C9717B400D36F21 /* sg_socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE070C9717B400D36F21 /* sg_socket.cpp */; };
+ 4315BE580C9717B400D36F21 /* ossimPlanetOssimImageLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE080C9717B400D36F21 /* ossimPlanetOssimImageLayer.cpp */; };
+ 4315BE590C9717B400D36F21 /* ul.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE090C9717B400D36F21 /* ul.cpp */; };
+ 4315BE5A0C9717B400D36F21 /* ulList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE0A0C9717B400D36F21 /* ulList.cpp */; };
+ 4315BE5B0C9717B400D36F21 /* ossimPlanetLandReaderWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE0B0C9717B400D36F21 /* ossimPlanetLandReaderWriter.cpp */; };
+ 4315BE5C0C9717B400D36F21 /* ossimPlanetLandCullCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE0C0C9717B400D36F21 /* ossimPlanetLandCullCallback.cpp */; };
+ 4315BE5D0C9717B400D36F21 /* ossimPlanetElevationDatabaseGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE0D0C9717B400D36F21 /* ossimPlanetElevationDatabaseGroup.cpp */; };
+ 4315BE5E0C9717B400D36F21 /* ossimPlanetElevationDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4315BE0E0C9717B400D36F21 /* ossimPlanetElevationDatabase.cpp */; };
+ 4315BEC80C9717E400D36F21 /* ossimPlanetLandTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE5F0C9717E400D36F21 /* ossimPlanetLandTreeNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEC90C9717E400D36F21 /* ossimPlanetLandNormalType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE600C9717E400D36F21 /* ossimPlanetLandNormalType.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BECA0C9717E400D36F21 /* ossimPlanetKmlLayerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE610C9717E400D36F21 /* ossimPlanetKmlLayerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BECB0C9717E400D36F21 /* netBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE620C9717E400D36F21 /* netBuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BECC0C9717E400D36F21 /* ossimPlanetLand.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE630C9717E400D36F21 /* ossimPlanetLand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BECD0C9717E400D36F21 /* ossimPlanetBillboardIcon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE640C9717E400D36F21 /* ossimPlanetBillboardIcon.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BECF0C9717E400D36F21 /* ossimPlanetElevationDatabaseGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE660C9717E400D36F21 /* ossimPlanetElevationDatabaseGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED00C9717E400D36F21 /* ossimPlanetIdolLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE670C9717E400D36F21 /* ossimPlanetIdolLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED20C9717E400D36F21 /* ossimPlanetIdManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE690C9717E400D36F21 /* ossimPlanetIdManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED30C9717E400D36F21 /* ossimPlanetLandReaderWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE6A0C9717E400D36F21 /* ossimPlanetLandReaderWriter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED40C9717E400D36F21 /* ossimPlanetUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE6B0C9717E400D36F21 /* ossimPlanetUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED50C9717E400D36F21 /* ossimPlanetThreadPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE6C0C9717E400D36F21 /* ossimPlanetThreadPool.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED60C9717E400D36F21 /* ossimPlanetPlaneGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE6D0C9717E400D36F21 /* ossimPlanetPlaneGrid.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED70C9717E400D36F21 /* ossimPlanetPagedRequestNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE6E0C9717E400D36F21 /* ossimPlanetPagedRequestNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED80C9717E400D36F21 /* ossimPlanetPagedLandLodRefreshType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE6F0C9717E400D36F21 /* ossimPlanetPagedLandLodRefreshType.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BED90C9717E400D36F21 /* ossimPlanetLandNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE700C9717E400D36F21 /* ossimPlanetLandNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEDA0C9717E400D36F21 /* ossimPlanetIoSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE710C9717E400D36F21 /* ossimPlanetIoSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEDB0C9717E400D36F21 /* ossimPlanetInteractionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE720C9717E400D36F21 /* ossimPlanetInteractionController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEDC0C9717E400D36F21 /* ulLocal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE730C9717E400D36F21 /* ulLocal.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEDD0C9717E400D36F21 /* ul.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE740C9717E400D36F21 /* ul.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEDE0C9717E400D36F21 /* ossimPlanetInputDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE750C9717E400D36F21 /* ossimPlanetInputDevice.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEDF0C9717E400D36F21 /* ossimPlanetShaderProgramSetup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE760C9717E400D36F21 /* ossimPlanetShaderProgramSetup.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE00C9717E400D36F21 /* ossimPlanetSetup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE770C9717E400D36F21 /* ossimPlanetSetup.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE10C9717E400D36F21 /* ossimPlanetBoundingBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE780C9717E400D36F21 /* ossimPlanetBoundingBox.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE20C9717E400D36F21 /* ossimPlanetIoSocketServerChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE790C9717E400D36F21 /* ossimPlanetIoSocketServerChannel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE30C9717E400D36F21 /* ossimPlanetPrimaryBody.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE7A0C9717E400D36F21 /* ossimPlanetPrimaryBody.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE40C9717E400D36F21 /* ossimPlanetSocketNetworkConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE7B0C9717E400D36F21 /* ossimPlanetSocketNetworkConnection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE50C9717E400D36F21 /* iochannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE7C0C9717E400D36F21 /* iochannel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE60C9717E400D36F21 /* ossimPlanetIconGeom.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE7D0C9717E400D36F21 /* ossimPlanetIconGeom.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE70C9717E400D36F21 /* ossimPlanetTextureLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE7E0C9717E400D36F21 /* ossimPlanetTextureLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE80C9717E400D36F21 /* ossimPlanetTexture2D.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE7F0C9717E400D36F21 /* ossimPlanetTexture2D.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEE90C9717E400D36F21 /* ossimPlanetAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE800C9717E400D36F21 /* ossimPlanetAction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEEA0C9717E400D36F21 /* ossimPlanetServerMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE810C9717E400D36F21 /* ossimPlanetServerMessageHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEEB0C9717E400D36F21 /* ossimPlanetSceneView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE820C9717E400D36F21 /* ossimPlanetSceneView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEEC0C9717E400D36F21 /* ossimPlanetManipulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE830C9717E400D36F21 /* ossimPlanetManipulator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEED0C9717E400D36F21 /* ossimPlanetWmsImageLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE840C9717E400D36F21 /* ossimPlanetWmsImageLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEEE0C9717E400D36F21 /* ossimPlanetThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE850C9717E400D36F21 /* ossimPlanetThread.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEEF0C9717E400D36F21 /* ossimPlanetTextureLayerRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE860C9717E400D36F21 /* ossimPlanetTextureLayerRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF00C9717E400D36F21 /* netChat.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE870C9717E400D36F21 /* netChat.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF10C9717E400D36F21 /* ossimPlanetTextureLayerGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE880C9717E400D36F21 /* ossimPlanetTextureLayerGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF20C9717E400D36F21 /* ossimPlanetTextureLayerFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE890C9717E400D36F21 /* ossimPlanetTextureLayerFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF30C9717E400D36F21 /* ossimPlanetOssimImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE8A0C9717E400D36F21 /* ossimPlanetOssimImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF40C9717E400D36F21 /* ossimPlanetOrthoFlatLandNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE8B0C9717E400D36F21 /* ossimPlanetOrthoFlatLandNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF50C9717E400D36F21 /* ossimPlanetServerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE8C0C9717E400D36F21 /* ossimPlanetServerThread.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF60C9717E400D36F21 /* ossimPlanetIoThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE8D0C9717E400D36F21 /* ossimPlanetIoThread.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF70C9717E400D36F21 /* ossimPlanet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE8E0C9717E400D36F21 /* ossimPlanet.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF80C9717E400D36F21 /* ossimPlanetOssimImageLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE8F0C9717E400D36F21 /* ossimPlanetOssimImageLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEF90C9717E400D36F21 /* ossimPlanetThreadImp.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE900C9717E400D36F21 /* ossimPlanetThreadImp.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEFB0C9717E400D36F21 /* ossimPlanetLandTextureRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE920C9717E400D36F21 /* ossimPlanetLandTextureRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEFC0C9717E400D36F21 /* ossimPlanetLandCullCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE930C9717E400D36F21 /* ossimPlanetLandCullCallback.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEFD0C9717E400D36F21 /* ossimPlanetConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE940C9717E400D36F21 /* ossimPlanetConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEFE0C9717E400D36F21 /* ossimPlanetNetworkConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE950C9717E400D36F21 /* ossimPlanetNetworkConnection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BEFF0C9717E400D36F21 /* ossimPlanetKml.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE960C9717E400D36F21 /* ossimPlanetKml.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF010C9717E400D36F21 /* ossimPlanetExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE980C9717E400D36F21 /* ossimPlanetExport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF020C9717E400D36F21 /* netMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE990C9717E400D36F21 /* netMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF030C9717E400D36F21 /* ossimPlanetIo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE9A0C9717E400D36F21 /* ossimPlanetIo.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF040C9717E400D36F21 /* ossimPlanetJpegImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE9B0C9717E400D36F21 /* ossimPlanetJpegImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF050C9717E400D36F21 /* ossimPlanetLookAt.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE9C0C9717E400D36F21 /* ossimPlanetLookAt.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF080C9717E400D36F21 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BE9F0C9717E400D36F21 /* net.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF090C9717E400D36F21 /* ulRTTI.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA00C9717E400D36F21 /* ulRTTI.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF0A0C9717E400D36F21 /* netChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA10C9717E400D36F21 /* netChannel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF0B0C9717E400D36F21 /* ossimPlanetElevationGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA20C9717E400D36F21 /* ossimPlanetElevationGrid.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF0C0C9717E400D36F21 /* ossimPlanetIntersectUserData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA30C9717E400D36F21 /* ossimPlanetIntersectUserData.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF0D0C9717E400D36F21 /* ossimPlanetLabelGeom.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA40C9717E400D36F21 /* ossimPlanetLabelGeom.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF0E0C9717E400D36F21 /* ossimPlanetGeocoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA50C9717E400D36F21 /* ossimPlanetGeocoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF0F0C9717E400D36F21 /* ossimPlanetLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA60C9717E400D36F21 /* ossimPlanetLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF100C9717E400D36F21 /* netMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA70C9717E400D36F21 /* netMonitor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF110C9717E400D36F21 /* ossimPlanetId.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEA80C9717E400D36F21 /* ossimPlanetId.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF130C9717E400D36F21 /* ossimPlanetActionRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEAA0C9717E400D36F21 /* ossimPlanetActionRouter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF140C9717E400D36F21 /* ossimPlanetSrtmElevationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEAB0C9717E400D36F21 /* ossimPlanetSrtmElevationDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF150C9717E400D36F21 /* ossimPlanetStandardTextureLayerFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEAC0C9717E400D36F21 /* ossimPlanetStandardTextureLayerFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF160C9717E400D36F21 /* ossimPlanetActionReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEAD0C9717E400D36F21 /* ossimPlanetActionReceiver.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF170C9717E400D36F21 /* sg_file.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEAE0C9717E400D36F21 /* sg_file.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF180C9717E400D36F21 /* ossimPlanetYahooGeocoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEAF0C9717E400D36F21 /* ossimPlanetYahooGeocoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF190C9717E400D36F21 /* ossimPlanetIoMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB00C9717E400D36F21 /* ossimPlanetIoMessageHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF1A0C9717E400D36F21 /* ossimPlanetElevationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB10C9717E400D36F21 /* ossimPlanetElevationDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF1B0C9717E400D36F21 /* compiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB20C9717E400D36F21 /* compiler.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF1C0C9717E400D36F21 /* ossimPlanetLandCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB30C9717E400D36F21 /* ossimPlanetLandCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF1D0C9717E400D36F21 /* ossimPlanetExtents.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB40C9717E400D36F21 /* ossimPlanetExtents.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF1E0C9717E400D36F21 /* ossimPlanetKmlReaderWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB50C9717E400D36F21 /* ossimPlanetKmlReaderWriter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF1F0C9717E400D36F21 /* ossimPlanetDtedElevationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB60C9717E400D36F21 /* ossimPlanetDtedElevationDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF200C9717E400D36F21 /* ossimPlanetNavigator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB70C9717E400D36F21 /* ossimPlanetNavigator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF210C9717E400D36F21 /* ossimPlanetImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB80C9717E400D36F21 /* ossimPlanetImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF220C9717E400D36F21 /* sg_socket_udp.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEB90C9717E400D36F21 /* sg_socket_udp.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF230C9717E400D36F21 /* sg_socket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEBA0C9717E400D36F21 /* sg_socket.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF240C9717E400D36F21 /* ossimPlanetCubeGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEBB0C9717E400D36F21 /* ossimPlanetCubeGrid.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF250C9717E400D36F21 /* ossimPlanetIdolBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEBC0C9717E400D36F21 /* ossimPlanetIdolBridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF270C9717E400D36F21 /* mkUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEBE0C9717E400D36F21 /* mkUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF280C9717E400D36F21 /* ossimPlanetLatLonHud.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEBF0C9717E400D36F21 /* ossimPlanetLatLonHud.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF290C9717E400D36F21 /* ossimPlanetClientThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC00C9717E400D36F21 /* ossimPlanetClientThread.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF2A0C9717E400D36F21 /* ossimPlanetIoRoutableMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC10C9717E400D36F21 /* ossimPlanetIoRoutableMessageHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF2B0C9717E400D36F21 /* ossimPlanetPagedLandLod.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC20C9717E400D36F21 /* ossimPlanetPagedLandLod.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF2C0C9717E400D36F21 /* ossimPlanetWmsClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC30C9717E400D36F21 /* ossimPlanetWmsClient.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF2D0C9717E400D36F21 /* netSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC40C9717E400D36F21 /* netSocket.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF2E0C9717E400D36F21 /* ossimPlanetKmlLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC50C9717E400D36F21 /* ossimPlanetKmlLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF2F0C9717E400D36F21 /* ossimPlanetGridUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC60C9717E400D36F21 /* ossimPlanetGridUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4315BF300C9717E400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4315BEC70C9717E400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43244C830F742D70002F5FA3 /* ossimPlanetReentrantMutex.h in Headers */ = {isa = PBXBuildFile; fileRef = 43244C820F742D70002F5FA3 /* ossimPlanetReentrantMutex.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 432933BB10FE531E00C66EB8 /* OpenThreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 432933BA10FE531E00C66EB8 /* OpenThreads.framework */; };
+ 432933E110FE577D00C66EB8 /* OpenThreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 432933BA10FE531E00C66EB8 /* OpenThreads.framework */; };
+ 432933E410FE579100C66EB8 /* osg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAA10FE11A700C7202A /* osg.framework */; };
+ 4329349110FE57A200C66EB8 /* osgViewer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABB110FE11C000C7202A /* osgViewer.framework */; };
+ 432934AB10FE57AC00C66EB8 /* osgGA.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAC10FE11AC00C7202A /* osgGA.framework */; };
+ 432934C210FE57AF00C66EB8 /* osg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAA10FE11A700C7202A /* osg.framework */; };
+ 432934C510FE57C800C66EB8 /* OpenThreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 432933BA10FE531E00C66EB8 /* OpenThreads.framework */; };
+ 432934CA10FE57D600C66EB8 /* osgDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAE10FE11C000C7202A /* osgDB.framework */; };
+ 4329351A10FE57FA00C66EB8 /* OpenThreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 432933BA10FE531E00C66EB8 /* OpenThreads.framework */; };
+ 4329351B10FE57FA00C66EB8 /* osgDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAE10FE11C000C7202A /* osgDB.framework */; };
+ 4329351C10FE57FA00C66EB8 /* osgUtil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABB010FE11C000C7202A /* osgUtil.framework */; };
+ 4329351D10FE57FA00C66EB8 /* osgViewer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABB110FE11C000C7202A /* osgViewer.framework */; };
+ 4329351E10FE57FA00C66EB8 /* osgGA.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAC10FE11AC00C7202A /* osgGA.framework */; };
+ 4329351F10FE57FA00C66EB8 /* osg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAA10FE11A700C7202A /* osg.framework */; };
+ 4329352F10FE591500C66EB8 /* osgText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4306ABAF10FE11C000C7202A /* osgText.framework */; };
+ 432D60B60CB548C800F15133 /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 432D60B30CB548C800F15133 /* ioapi.c */; };
+ 432D60B70CB548C800F15133 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 432D60B40CB548C800F15133 /* unzip.c */; };
+ 432D60B80CB548C800F15133 /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 432D60B50CB548C800F15133 /* zip.c */; };
+ 432D60BC0CB548DE00F15133 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 432D60B90CB548DE00F15133 /* ioapi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 432D60BD0CB548DE00F15133 /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = 432D60BA0CB548DE00F15133 /* unzip.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 432D60BE0CB548DE00F15133 /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = 432D60BB0CB548DE00F15133 /* zip.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 432FACB90CC4F2D6004D5C1D /* ossimPlanetCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 432FACB80CC4F2D6004D5C1D /* ossimPlanetCallback.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 433A4CCA100CED8D000B969C /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF4F60B1CE11D00F7886A /* ossim.framework */; };
+ 433A4CCF100CED8D000B969C /* ossimPlanet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D07F2C80486CC7A007CD1D0 /* ossimPlanet.framework */; };
+ 433A4CF7100CEDD2000B969C /* ossimplanettest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 433A4CF6100CEDD2000B969C /* ossimplanettest.cpp */; };
+ 433E7EC20D32B9CF00BA05D0 /* ossimPlanetApi.h in Headers */ = {isa = PBXBuildFile; fileRef = 433E7EC10D32B9CF00BA05D0 /* ossimPlanetApi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 433E7EC80D32B9EC00BA05D0 /* ossimPlanetApi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 433E7EC70D32B9EC00BA05D0 /* ossimPlanetApi.cpp */; };
+ 4345891C0FD3F95900046CB5 /* ossimPlanetAnimatedPointModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4345891B0FD3F95900046CB5 /* ossimPlanetAnimatedPointModel.cpp */; };
+ 4345891E0FD3F96C00046CB5 /* ossimPlanetAnimatedPointModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4345891D0FD3F96C00046CB5 /* ossimPlanetAnimatedPointModel.h */; };
+ 43463BC00FCF16DD0027D845 /* ossimPlanetAnimationPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 43463BBF0FCF16DD0027D845 /* ossimPlanetAnimationPath.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43463BD70FCF78850027D845 /* ossimPlanetAnimationPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43463BD60FCF78850027D845 /* ossimPlanetAnimationPath.cpp */; };
+ 434E72B910DAACEE005EBB18 /* ossimPlanetOssimElevationDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 434E72B810DAACEE005EBB18 /* ossimPlanetOssimElevationDatabase.cpp */; };
+ 434E72BC10DAAD15005EBB18 /* ossimPlanetOssimElevationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 434E72BB10DAAD15005EBB18 /* ossimPlanetOssimElevationDatabase.h */; };
+ 434EDC180D2BCA2600EDC08A /* ossimPlanetLayerRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 434EDC170D2BCA2600EDC08A /* ossimPlanetLayerRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 434EDC1A0D2BCC8000EDC08A /* ossimPlanetLayerFactoryBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 434EDC190D2BCC8000EDC08A /* ossimPlanetLayerFactoryBase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 434EDC3C0D2BD04400EDC08A /* ossimPlanetLayerFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 434EDC3B0D2BD04400EDC08A /* ossimPlanetLayerFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 434EDC400D2BD20500EDC08A /* ossimPlanetLayerRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 434EDC3E0D2BD20500EDC08A /* ossimPlanetLayerRegistry.cpp */; };
+ 434EDC7C0D2BD8D200EDC08A /* ossimPlanetLayerFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 434EDC7A0D2BD8D200EDC08A /* ossimPlanetLayerFactory.cpp */; };
+ 4351096E0FCC130A0065BA0E /* ossimPlanetViewMatrixBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4351096D0FCC130A0065BA0E /* ossimPlanetViewMatrixBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 435109740FCC134C0065BA0E /* ossimPlanetViewMatrixBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 435109730FCC134C0065BA0E /* ossimPlanetViewMatrixBuilder.cpp */; };
+ 435BD1FC0F09848100CEAEAD /* ossimPlanetViewer.h in Headers */ = {isa = PBXBuildFile; fileRef = 435BD1FB0F09848100CEAEAD /* ossimPlanetViewer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43669A930CD177A400F1832B /* ossimPlanetSousaLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 43669A920CD177A400F1832B /* ossimPlanetSousaLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43669A950CD177CD00F1832B /* ossimPlanetSousaLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43669A940CD177CD00F1832B /* ossimPlanetSousaLayer.cpp */; };
+ 4377D4281029BB5800B6652D /* ossimPlanetCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 4377D4271029BB5800B6652D /* ossimPlanetCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4377D42A1029BB7000B6652D /* ossimPlanetCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4377D4291029BB7000B6652D /* ossimPlanetCache.cpp */; };
+ 4377D6F8102C509900B6652D /* ossimPlanetKmlNetworkLinkNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4377D6F7102C509900B6652D /* ossimPlanetKmlNetworkLinkNode.cpp */; };
+ 4377D6FB102C50AD00B6652D /* ossimPlanetKmlNetworkLinkNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4377D6FA102C50AD00B6652D /* ossimPlanetKmlNetworkLinkNode.h */; };
+ 437D9DE70FC3FFA60018F889 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437D9DE60FC3FFA60018F889 /* OpenGL.framework */; };
+ 43A113950D520D5D00DE3CF3 /* ossimPlanetNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A113940D520D5D00DE3CF3 /* ossimPlanetNode.cpp */; };
+ 43A113980D520D7100DE3CF3 /* ossimPlanetNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A113970D520D7100DE3CF3 /* ossimPlanetNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43A113DF0D520F3600DE3CF3 /* ossimPlanetNodeFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A113DC0D520F3600DE3CF3 /* ossimPlanetNodeFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43A113E00D520F3600DE3CF3 /* ossimPlanetNodeRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A113DD0D520F3600DE3CF3 /* ossimPlanetNodeRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43A113E10D520F3600DE3CF3 /* ossimPlanetNodeFactoryBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A113DE0D520F3600DE3CF3 /* ossimPlanetNodeFactoryBase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43A113E70D520F8900DE3CF3 /* ossimPlanetNodeFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A113E50D520F8900DE3CF3 /* ossimPlanetNodeFactory.cpp */; };
+ 43A113E80D520F8900DE3CF3 /* ossimPlanetNodeRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A113E60D520F8900DE3CF3 /* ossimPlanetNodeRegistry.cpp */; };
+ 43A52F150D4FA87100DB4777 /* ossimPlanetVisitors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A52F140D4FA87100DB4777 /* ossimPlanetVisitors.cpp */; };
+ 43AA128F0D77ADF90020DF13 /* ossimPlanetXmlAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43AA128E0D77ADF90020DF13 /* ossimPlanetXmlAction.cpp */; };
+ 43AB5F570FF9434D004874C2 /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF4F60B1CE11D00F7886A /* ossim.framework */; };
+ 43AB5FAF0FF99226004874C2 /* ossimPlanetEphemeris.h in Headers */ = {isa = PBXBuildFile; fileRef = 43AB5FAE0FF99226004874C2 /* ossimPlanetEphemeris.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43AB5FB30FF99240004874C2 /* ossimPlanetEphemeris.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43AB5FB20FF99240004874C2 /* ossimPlanetEphemeris.cpp */; };
+ 43BC2F8D0F8D13A600838B40 /* ossimPlanetTileRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43BC2F8C0F8D13A600838B40 /* ossimPlanetTileRequest.cpp */; };
+ 43BC2F8F0F8D13C600838B40 /* ossimPlanetTileRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 43BC2F8E0F8D13C600838B40 /* ossimPlanetTileRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43C443DE0D4A2179004BDD99 /* ossimPlanetOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C443DD0D4A2179004BDD99 /* ossimPlanetOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43C443E30D4A2C6D004BDD99 /* ossimPlanetOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43C443E10D4A2C6D004BDD99 /* ossimPlanetOperation.cpp */; };
+ 43C6E2B70FEFB50E004B52F7 /* ossimplanetklv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43C6E2B60FEFB50E004B52F7 /* ossimplanetklv.cpp */; };
+ 43C6E2C90FEFB531004B52F7 /* ossimplanetviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43C6E2C30FEFB531004B52F7 /* ossimplanetviewer.cpp */; };
+ 43C6E2CB0FEFB572004B52F7 /* ossimPredator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEB5ECF10D0F2284000CF6B2 /* ossimPredator.framework */; };
+ 43C6E2CC0FEFB580004B52F7 /* ossimPlanet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D07F2C80486CC7A007CD1D0 /* ossimPlanet.framework */; };
+ 43C6E5660FF00474004B52F7 /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF4F60B1CE11D00F7886A /* ossim.framework */; };
+ 43C8A82E0CAACB4E00EE840F /* ossimPlanetKmlPlacemarkNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C8A82D0CAACB4E00EE840F /* ossimPlanetKmlPlacemarkNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43C8A8320CAACB6500EE840F /* ossimPlanetKmlPlacemarkNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43C8A8310CAACB6500EE840F /* ossimPlanetKmlPlacemarkNode.cpp */; };
+ 43CA034E0DD34451003EC1AB /* ossimPlanetArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CA034C0DD34451003EC1AB /* ossimPlanetArchive.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43CA034F0DD34451003EC1AB /* ossimPlanetArchiveMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CA034D0DD34451003EC1AB /* ossimPlanetArchiveMapping.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43CA03520DD34464003EC1AB /* ossimPlanetArchiveMapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43CA03500DD34464003EC1AB /* ossimPlanetArchiveMapping.cpp */; };
+ 43CA03530DD34464003EC1AB /* ossimPlanetArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43CA03510DD34464003EC1AB /* ossimPlanetArchive.cpp */; };
+ 43D65A310F6839F1006C6786 /* ossimPlanetTerrainLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 43D65A300F6839F1006C6786 /* ossimPlanetTerrainLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43D65A530F683B15006C6786 /* ossimPlanetTerrainLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43D65A520F683B15006C6786 /* ossimPlanetTerrainLayer.cpp */; };
+ 43D7ECB310FE1F8500762FA7 /* gpstk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43D7ECB210FE1F8500762FA7 /* gpstk.framework */; };
+ 43D8A1090D818E2200A60690 /* ossimPlanet.xsd in Resources */ = {isa = PBXBuildFile; fileRef = 43D8A1080D818E2200A60690 /* ossimPlanet.xsd */; };
+ 43D9C7E010A4BBB900BA9119 /* ossimPlanetCacheTextureLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43D9C7DF10A4BBB900BA9119 /* ossimPlanetCacheTextureLayer.cpp */; };
+ 43D9C7E510A4BC0F00BA9119 /* ossimPlanetCacheTextureLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 43D9C7E410A4BC0F00BA9119 /* ossimPlanetCacheTextureLayer.h */; };
+ 43E957E00D2931C000D31E60 /* ossimPlanetRefBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 43E957DF0D2931C000D31E60 /* ossimPlanetRefBlock.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43FDA2D70D770D0700945FA0 /* ossimPlanetDestinationCommandAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 43FDA2D60D770D0700945FA0 /* ossimPlanetDestinationCommandAction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43FDA2DA0D77274F00945FA0 /* ossimPlanetDestinationCommandAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43FDA2D90D77274F00945FA0 /* ossimPlanetDestinationCommandAction.cpp */; };
+ 43FDA3D30D77495200945FA0 /* ossimPlanetXmlAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 43FDA3D20D77495200945FA0 /* ossimPlanetXmlAction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43FF0C201021065500CEA135 /* ossimPlanetCloudLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 43FF0C1F1021065500CEA135 /* ossimPlanetCloudLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 43FF0C261021068E00CEA135 /* ossimPlanetCloudLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43FF0C251021068E00CEA135 /* ossimPlanetCloudLayer.cpp */; };
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+ EE0517BC0EE81BB6009EC91D /* ossimPlanetViewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE0517BB0EE81BB6009EC91D /* ossimPlanetViewer.cpp */; };
+ EE26B23A0F39CB8400D4028C /* ossimPlanetElevationRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = EE26B2390F39CB8400D4028C /* ossimPlanetElevationRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE26B23D0F39CC0D00D4028C /* ossimPlanetElevationRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE26B23C0F39CC0D00D4028C /* ossimPlanetElevationRegistry.cpp */; };
+ EE26B2680F39DD1100D4028C /* ossimPlanetElevationFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE26B2670F39DD1100D4028C /* ossimPlanetElevationFactory.cpp */; };
+ EE26B26A0F39DD2000D4028C /* ossimPlanetElevationFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EE26B2690F39DD2000D4028C /* ossimPlanetElevationFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE2F90FD0EB5E188003D424A /* ossimPlanetMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = EE2F90FC0EB5E188003D424A /* ossimPlanetMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE5403650F5D7030001139DD /* ossimPlanetTerrain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE5403640F5D7030001139DD /* ossimPlanetTerrain.cpp */; };
+ EE5403670F5D7041001139DD /* ossimPlanetTerrain.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5403660F5D7041001139DD /* ossimPlanetTerrain.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE54036A0F5D74F5001139DD /* ossimPlanetTerrainTile.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5403690F5D74F5001139DD /* ossimPlanetTerrainTile.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE5403790F5D7522001139DD /* ossimPlanetTerrainTile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE5403780F5D7522001139DD /* ossimPlanetTerrainTile.cpp */; };
+ EE5403EB0F5D8C42001139DD /* ossimPlanetGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE5403EA0F5D8C42001139DD /* ossimPlanetGrid.cpp */; };
+ EE5403EE0F5D8C50001139DD /* ossimPlanetGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5403ED0F5D8C50001139DD /* ossimPlanetGrid.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE5403F10F5D8DDE001139DD /* ossimPlanetTerrainTileId.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5403F00F5D8DDE001139DD /* ossimPlanetTerrainTileId.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE5404550F5E21CF001139DD /* ossimPlanetTerrainTechnique.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE5404540F5E21CF001139DD /* ossimPlanetTerrainTechnique.cpp */; };
+ EE5404570F5E21DD001139DD /* ossimPlanetTerrainTechnique.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5404560F5E21DD001139DD /* ossimPlanetTerrainTechnique.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE54045A0F5E24D2001139DD /* ossimPlanetTerrainGeometryTechnique.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5404590F5E24D2001139DD /* ossimPlanetTerrainGeometryTechnique.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE5404660F5E24EC001139DD /* ossimPlanetTerrainGeometryTechnique.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE5404650F5E24EC001139DD /* ossimPlanetTerrainGeometryTechnique.cpp */; };
+ EE5409A10F615143001139DD /* ossimPlanetPointModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE5409A00F615143001139DD /* ossimPlanetPointModel.cpp */; };
+ EE5409A30F61516D001139DD /* ossimPlanetPointModel.h in Headers */ = {isa = PBXBuildFile; fileRef = EE5409A20F61516D001139DD /* ossimPlanetPointModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE540A8F0F61A503001139DD /* ossimPlanetGeoRefModel.h in Headers */ = {isa = PBXBuildFile; fileRef = EE540A8E0F61A503001139DD /* ossimPlanetGeoRefModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE69A3550B28842B00C91DD1 /* wms.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE69A3500B2883FA00C91DD1 /* wms.framework */; };
+ EE9B0A4D0F6463A500394285 /* ossimPlanetLsrSpaceTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9B0A4C0F6463A500394285 /* ossimPlanetLsrSpaceTransform.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EE9B0A700F6463C400394285 /* ossimPlanetLsrSpaceTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE9B0A6F0F6463C400394285 /* ossimPlanetLsrSpaceTransform.cpp */; };
+ EEB5ECDA0D0F214E000CF6B2 /* ossimPlanetVideoLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = EEB5ECD80D0F214E000CF6B2 /* ossimPlanetVideoLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EEB5ECE50D0F220C000CF6B2 /* ossimPlanetVideoLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEB5ECE40D0F220C000CF6B2 /* ossimPlanetVideoLayer.cpp */; };
+ EEB5ECF20D0F2292000CF6B2 /* ossimPredator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEB5ECF10D0F2284000CF6B2 /* ossimPredator.framework */; };
+ EEB5EDDC0D101235000CF6B2 /* ossimPlanetPredatorVideoLayerNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEB5EDDB0D101235000CF6B2 /* ossimPlanetPredatorVideoLayerNode.cpp */; };
+ EEB5EDDE0D101268000CF6B2 /* ossimPlanetPredatorVideoLayerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = EEB5EDDD0D101268000CF6B2 /* ossimPlanetPredatorVideoLayerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EEBDD68E0D464823009DB3D5 /* ossimPlanetAnnotationLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = EEBDD68D0D464823009DB3D5 /* ossimPlanetAnnotationLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EEBDD6920D465A0B009DB3D5 /* ossimPlanetAnnotationLayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEBDD6900D465A0B009DB3D5 /* ossimPlanetAnnotationLayer.cpp */; };
+ EEBDD6CC0D46E214009DB3D5 /* ossimPlanetAnnotationLayerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = EEBDD6CB0D46E214009DB3D5 /* ossimPlanetAnnotationLayerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EEBDD6CF0D46E3AC009DB3D5 /* ossimPlanetAnnotationLayerNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEBDD6CE0D46E3AC009DB3D5 /* ossimPlanetAnnotationLayerNode.cpp */; };
+ EEBDDA7A0D491078009DB3D5 /* ossimPlanetVideoLayerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = EEBDDA790D491078009DB3D5 /* ossimPlanetVideoLayerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EED173960CA0174100DF3588 /* ossimPlanetFadeText.h in Headers */ = {isa = PBXBuildFile; fileRef = EED173950CA0174100DF3588 /* ossimPlanetFadeText.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EED173980CA0174E00DF3588 /* ossimPlanetFadeText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EED173970CA0174E00DF3588 /* ossimPlanetFadeText.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 186EF4F50B1CE11D00F7886A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 8D07F2C80486CC7A007CD1D0;
+ remoteInfo = ossim;
+ };
+ 433A4CC6100CED8D000B969C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = ossimPlanet;
+ };
+ 435310B61044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628031042E368002A87C7;
+ remoteInfo = "template-app";
+ };
+ 435310B81044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628151042E3B0002A87C7;
+ remoteInfo = "ossim-adrg-dump";
+ };
+ 435310BA1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628371042E3F6002A87C7;
+ remoteInfo = "ossim-applanix2ogeom";
+ };
+ 435310BC1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628551042E461002A87C7;
+ remoteInfo = "ossim-band-merge";
+ };
+ 435310BE1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628741042E4AC002A87C7;
+ remoteInfo = "ossim-btoa";
+ };
+ 435310C01044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628861042E4D1002A87C7;
+ remoteInfo = "ossim-chgkwval";
+ };
+ 435310C21044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 4336289F1042E52A002A87C7;
+ remoteInfo = "ossim-cmm";
+ };
+ 435310C41044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628B91042E560002A87C7;
+ remoteInfo = "ossim-computeSrtmStats";
+ };
+ 435310C61044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628D61042E59C002A87C7;
+ remoteInfo = "ossim-correl";
+ };
+ 435310C81044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433628F11042E5D1002A87C7;
+ remoteInfo = "ossim-create-cg";
+ };
+ 435310CA1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 4336290B1042E607002A87C7;
+ remoteInfo = "ossim-create-histo";
+ };
+ 435310D21044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433629811042E712002A87C7;
+ remoteInfo = "ossim-dms2deg";
+ };
+ 435310D41044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 4336299D1042E759002A87C7;
+ remoteInfo = "ossim-dump-ocg";
+ };
+ 435310D61044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433629B51042E77C002A87C7;
+ remoteInfo = "ossim-ecg2ocg";
+ };
+ 435310D81044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433629D01042E7B1002A87C7;
+ remoteInfo = "ossim-extract-vertices";
+ };
+ 435310DA1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 433629E41042E807002A87C7;
+ remoteInfo = "ossim-foo";
+ };
+ 435310DE1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362A2D1042E88F002A87C7;
+ remoteInfo = "ossim-height";
+ };
+ 435310E01044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362A4B1042E8BD002A87C7;
+ remoteInfo = "ossim-icp";
+ };
+ 435310E21044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362A631042E8EE002A87C7;
+ remoteInfo = "ossim-igen";
+ };
+ 435310E41044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362A7D1042E914002A87C7;
+ remoteInfo = "ossim-img2md";
+ };
+ 435310E61044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362A9A1042E955002A87C7;
+ remoteInfo = "ossim-img2rr";
+ };
+ 435310E81044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362AB41042E981002A87C7;
+ remoteInfo = "ossim-info";
+ };
+ 435310EA1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362AD21042EA43002A87C7;
+ remoteInfo = "ossim-modopt";
+ };
+ 435310EC1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362AEF1042EA81002A87C7;
+ remoteInfo = "ossim-mosaic";
+ };
+ 435310F21044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362B471042EB45002A87C7;
+ remoteInfo = "ossim-ogeom2ogeom";
+ };
+ 435310F41044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362B641042EB70002A87C7;
+ remoteInfo = "ossim-orthoigen";
+ };
+ 435310F61044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362B801042EB9B002A87C7;
+ remoteInfo = "ossim-pixelflip";
+ };
+ 435310F81044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362B9B1042EBCE002A87C7;
+ remoteInfo = "ossim-prune";
+ };
+ 435310FC1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362BD21042EC26002A87C7;
+ remoteInfo = "ossim-rejout";
+ };
+ 435310FE1044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362BEE1042EC50002A87C7;
+ remoteInfo = "ossim-senint";
+ };
+ 435311001044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362C081042EC80002A87C7;
+ remoteInfo = "ossim-space-imaging";
+ };
+ 435311021044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362C221042ECAF002A87C7;
+ remoteInfo = "ossim-swapbytes";
+ };
+ 435311041044384C004A4474 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 43362C3C1042ECD6002A87C7;
+ remoteInfo = "ossim-tfw2ogeom";
+ };
+ 437A55AC0E789BB8000D89D5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 1FD5B7C80E75D3DC00FBD730;
+ remoteInfo = wmsurl;
+ };
+ 437A55AE0E789BB8000D89D5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 1FD5B7EA0E75D46700FBD730;
+ remoteInfo = wmscapabilities.cpp;
+ };
+ 437A55B00E789BB8000D89D5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 1FD5B7FE0E75D4C500FBD730;
+ remoteInfo = wmsgetmap;
+ };
+ 43AB5F2A0FF94015004874C2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = ossimPlanet;
+ };
+ 43DFCC070FF0F4E000FB2061 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 43C6E2900FEFB4D8004B52F7;
+ remoteInfo = ossimplanetklv;
+ };
+ 43DFCC090FF0F4E000FB2061 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 43C6E29B0FEFB4E9004B52F7;
+ remoteInfo = ossimplanetviewer;
+ };
+ EE69A34F0B2883FA00C91DD1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
+ remoteInfo = wms;
+ };
+ EE9D26600DD8891C005A8951 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = ossimPlanet;
+ };
+ EEB5ECF00D0F2284000CF6B2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EEB5ECEC0D0F2284000CF6B2 /* ossimPredator.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EE3F868B0D0DBB2300DFD3DF;
+ remoteInfo = ossimPredator;
+ };
+ EEB5EE590D103A4A000CF6B2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EEB5ECEC0D0F2284000CF6B2 /* ossimPredator.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = ossimPredator;
+ };
+ EEB5EE5B0D103A57000CF6B2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = ossim;
+ };
+ EEB5EE5D0D103A68000CF6B2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = wms;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = common_settings.xcconfig; path = ../../../ossim/xcode/ossim/common_settings.xcconfig; sourceTree = SOURCE_ROOT; };
+ 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ossim.xcodeproj; path = ../../../ossim/xcode/ossim/ossim.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 430485FD0F3CB80800B9C1E2 /* ossimPlanetDatabasePager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetDatabasePager.h; sourceTree = "<group>"; };
+ 4306ABAA10FE11A700C7202A /* osg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = osg.framework; path = ../../../ossim_dependencies/Frameworks/osg.framework; sourceTree = SOURCE_ROOT; };
+ 4306ABAC10FE11AC00C7202A /* osgGA.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = osgGA.framework; path = ../../../ossim_dependencies/Frameworks/osgGA.framework; sourceTree = SOURCE_ROOT; };
+ 4306ABAE10FE11C000C7202A /* osgDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = osgDB.framework; path = ../../../ossim_dependencies/Frameworks/osgDB.framework; sourceTree = SOURCE_ROOT; };
+ 4306ABAF10FE11C000C7202A /* osgText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = osgText.framework; path = ../../../ossim_dependencies/Frameworks/osgText.framework; sourceTree = SOURCE_ROOT; };
+ 4306ABB010FE11C000C7202A /* osgUtil.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = osgUtil.framework; path = ../../../ossim_dependencies/Frameworks/osgUtil.framework; sourceTree = SOURCE_ROOT; };
+ 4306ABB110FE11C000C7202A /* osgViewer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = osgViewer.framework; path = ../../../ossim_dependencies/Frameworks/osgViewer.framework; sourceTree = SOURCE_ROOT; };
+ 430C8F660CBBD0B8002BAF12 /* ossimPlanetCompass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetCompass.cpp; sourceTree = "<group>"; };
+ 430C8F680CBBD0CA002BAF12 /* ossimPlanetCompass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetCompass.h; sourceTree = "<group>"; };
+ 430D8E901100DA3F00EB0F96 /* ossimPlanetDepthPartitionNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetDepthPartitionNode.h; sourceTree = "<group>"; };
+ 430D8E931100DA5200EB0F96 /* ossimPlanetDistanceAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetDistanceAccumulator.h; sourceTree = "<group>"; };
+ 430D8E971100DB1F00EB0F96 /* ossimPlanetDepthPartitionNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetDepthPartitionNode.cpp; sourceTree = "<group>"; };
+ 430D8E981100DB1F00EB0F96 /* ossimPlanetDistanceAccumulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetDistanceAccumulator.cpp; sourceTree = "<group>"; };
+ 4314728E0CBE9F0F00EAADAB /* ossimPlanetVisitors.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetVisitors.h; sourceTree = "<group>"; };
+ 431476540CA838310090B3CE /* ossimPlanetKmlScreenOverlayNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetKmlScreenOverlayNode.cpp; sourceTree = "<group>"; };
+ 431476560CA838400090B3CE /* ossimPlanetKmlScreenOverlayNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKmlScreenOverlayNode.h; sourceTree = "<group>"; };
+ 4315BDBF0C9717B400D36F21 /* ossimPlanetDtedElevationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetDtedElevationDatabase.cpp; sourceTree = "<group>"; };
+ 4315BDC10C9717B400D36F21 /* ossimPlanetCubeGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetCubeGrid.cpp; sourceTree = "<group>"; };
+ 4315BDC20C9717B400D36F21 /* ossimPlanetWmsImageLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetWmsImageLayer.cpp; sourceTree = "<group>"; };
+ 4315BDC30C9717B400D36F21 /* ossimPlanetUtility.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetUtility.cpp; sourceTree = "<group>"; };
+ 4315BDC40C9717B400D36F21 /* ossimPlanetThreadPool.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetThreadPool.cpp; sourceTree = "<group>"; };
+ 4315BDC50C9717B400D36F21 /* ossimPlanetThreadImp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetThreadImp.cpp; sourceTree = "<group>"; };
+ 4315BDC60C9717B400D36F21 /* ossimPlanetThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetThread.cpp; sourceTree = "<group>"; };
+ 4315BDC70C9717B400D36F21 /* ossimPlanetTextureLayerRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTextureLayerRegistry.cpp; sourceTree = "<group>"; };
+ 4315BDC80C9717B400D36F21 /* ossimPlanetTextureLayerGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTextureLayerGroup.cpp; sourceTree = "<group>"; };
+ 4315BDC90C9717B400D36F21 /* ossimPlanetTextureLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTextureLayer.cpp; sourceTree = "<group>"; };
+ 4315BDCA0C9717B400D36F21 /* ossimPlanetStandardTextureLayerFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetStandardTextureLayerFactory.cpp; sourceTree = "<group>"; };
+ 4315BDCB0C9717B400D36F21 /* ossimPlanetSocketNetworkConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetSocketNetworkConnection.cpp; sourceTree = "<group>"; };
+ 4315BDCC0C9717B400D36F21 /* ossimPlanetShaderProgramSetup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetShaderProgramSetup.cpp; sourceTree = "<group>"; };
+ 4315BDCD0C9717B400D36F21 /* ossimPlanetServerThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetServerThread.cpp; sourceTree = "<group>"; };
+ 4315BDCE0C9717B400D36F21 /* ossimPlanetSceneView.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetSceneView.cpp; sourceTree = "<group>"; };
+ 4315BDCF0C9717B400D36F21 /* ossimPlanetPlaneGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetPlaneGrid.cpp; sourceTree = "<group>"; };
+ 4315BDD00C9717B400D36F21 /* ossimPlanetPagedLandLod.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetPagedLandLod.cpp; sourceTree = "<group>"; };
+ 4315BDD10C9717B400D36F21 /* ossimPlanetOssimImage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetOssimImage.cpp; sourceTree = "<group>"; };
+ 4315BDD20C9717B400D36F21 /* ossimPlanetManipulator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetManipulator.cpp; sourceTree = "<group>"; };
+ 4315BDD30C9717B400D36F21 /* ossimPlanetNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetNavigator.cpp; sourceTree = "<group>"; };
+ 4315BDD50C9717B400D36F21 /* ossimPlanetLookAt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLookAt.cpp; sourceTree = "<group>"; };
+ 4315BDD60C9717B400D36F21 /* ossimPlanetLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLayer.cpp; sourceTree = "<group>"; };
+ 4315BDD70C9717B400D36F21 /* ossimPlanetLatLonHud.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLatLonHud.cpp; sourceTree = "<group>"; };
+ 4315BDD80C9717B400D36F21 /* ulError.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ulError.cpp; sourceTree = "<group>"; };
+ 4315BDD90C9717B400D36F21 /* ulClock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ulClock.cpp; sourceTree = "<group>"; };
+ 4315BDDA0C9717B400D36F21 /* sg_socket_udp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sg_socket_udp.cpp; sourceTree = "<group>"; };
+ 4315BDDB0C9717B400D36F21 /* ossimPlanetYahooGeocoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetYahooGeocoder.cpp; sourceTree = "<group>"; };
+ 4315BDDC0C9717B400D36F21 /* ossimPlanetWmsClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetWmsClient.cpp; sourceTree = "<group>"; };
+ 4315BDDD0C9717B400D36F21 /* ossimPlanetIoThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetIoThread.cpp; sourceTree = "<group>"; };
+ 4315BDDE0C9717B400D36F21 /* ossimPlanetIoSocketServerChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetIoSocketServerChannel.cpp; sourceTree = "<group>"; };
+ 4315BDDF0C9717B400D36F21 /* ossimPlanetIoSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetIoSocket.cpp; sourceTree = "<group>"; };
+ 4315BDE00C9717B400D36F21 /* ossimPlanetIoRoutableMessageHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetIoRoutableMessageHandler.cpp; sourceTree = "<group>"; };
+ 4315BDE10C9717B400D36F21 /* ossimPlanetInteractionController.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetInteractionController.cpp; sourceTree = "<group>"; };
+ 4315BDE20C9717B400D36F21 /* ossimPlanetImage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetImage.cpp; sourceTree = "<group>"; };
+ 4315BDE30C9717B400D36F21 /* ossimPlanetIdManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetIdManager.cpp; sourceTree = "<group>"; };
+ 4315BDE40C9717B400D36F21 /* ossimPlanetClientThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetClientThread.cpp; sourceTree = "<group>"; };
+ 4315BDE50C9717B400D36F21 /* ossimPlanetBoundingBox.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetBoundingBox.cpp; sourceTree = "<group>"; };
+ 4315BDE60C9717B400D36F21 /* ossimPlanetBillboardIcon.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetBillboardIcon.cpp; sourceTree = "<group>"; };
+ 4315BDE70C9717B400D36F21 /* ossimPlanetKmlLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetKmlLayer.cpp; sourceTree = "<group>"; };
+ 4315BDE90C9717B400D36F21 /* ossimPlanetKml.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetKml.cpp; sourceTree = "<group>"; };
+ 4315BDEA0C9717B400D36F21 /* ossimPlanetJpegImage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetJpegImage.cpp; sourceTree = "<group>"; };
+ 4315BDEB0C9717B400D36F21 /* ossimPlanet.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanet.cpp; sourceTree = "<group>"; };
+ 4315BDEC0C9717B400D36F21 /* netSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = netSocket.cpp; sourceTree = "<group>"; };
+ 4315BDED0C9717B400D36F21 /* netMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = netMonitor.cpp; sourceTree = "<group>"; };
+ 4315BDEE0C9717B400D36F21 /* netMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = netMessage.cpp; sourceTree = "<group>"; };
+ 4315BDEF0C9717B400D36F21 /* netChat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = netChat.cpp; sourceTree = "<group>"; };
+ 4315BDF00C9717B400D36F21 /* netChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = netChannel.cpp; sourceTree = "<group>"; };
+ 4315BDF10C9717B400D36F21 /* netBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = netBuffer.cpp; sourceTree = "<group>"; };
+ 4315BDF20C9717B400D36F21 /* mkUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = mkUtils.cpp; sourceTree = "<group>"; };
+ 4315BDF30C9717B400D36F21 /* iochannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = iochannel.cpp; sourceTree = "<group>"; };
+ 4315BDF40C9717B400D36F21 /* ossimPlanetGeocoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetGeocoder.cpp; sourceTree = "<group>"; };
+ 4315BDF60C9717B400D36F21 /* ossimPlanetActionRouter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetActionRouter.cpp; sourceTree = "<group>"; };
+ 4315BDF70C9717B400D36F21 /* ossimPlanetActionReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetActionReceiver.cpp; sourceTree = "<group>"; };
+ 4315BDF80C9717B400D36F21 /* ossimPlanetAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetAction.cpp; sourceTree = "<group>"; };
+ 4315BDF90C9717B400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetGeneralRasterElevationDatabase.cpp; sourceTree = "<group>"; };
+ 4315BDFA0C9717B400D36F21 /* ossimPlanetElevationGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetElevationGrid.cpp; sourceTree = "<group>"; };
+ 4315BDFB0C9717B400D36F21 /* ulLinkedList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ulLinkedList.cpp; sourceTree = "<group>"; };
+ 4315BDFC0C9717B400D36F21 /* ossimPlanetLandCache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLandCache.cpp; sourceTree = "<group>"; };
+ 4315BDFD0C9717B400D36F21 /* ossimPlanetLand.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLand.cpp; sourceTree = "<group>"; };
+ 4315BDFE0C9717B400D36F21 /* ossimPlanetKmlLayerNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetKmlLayerNode.cpp; sourceTree = "<group>"; };
+ 4315BDFF0C9717B400D36F21 /* sg_file.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sg_file.cpp; sourceTree = "<group>"; };
+ 4315BE000C9717B400D36F21 /* ossimPlanetTexture2D.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTexture2D.cpp; sourceTree = "<group>"; };
+ 4315BE010C9717B400D36F21 /* ossimPlanetSrtmElevationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetSrtmElevationDatabase.cpp; sourceTree = "<group>"; };
+ 4315BE020C9717B400D36F21 /* ossimPlanetId.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetId.cpp; sourceTree = "<group>"; };
+ 4315BE030C9717B400D36F21 /* ossimPlanetIconGeom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetIconGeom.cpp; sourceTree = "<group>"; };
+ 4315BE050C9717B400D36F21 /* ossimPlanetGridUtility.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetGridUtility.cpp; sourceTree = "<group>"; };
+ 4315BE060C9717B400D36F21 /* ulRTTI.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ulRTTI.cpp; sourceTree = "<group>"; };
+ 4315BE070C9717B400D36F21 /* sg_socket.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sg_socket.cpp; sourceTree = "<group>"; };
+ 4315BE080C9717B400D36F21 /* ossimPlanetOssimImageLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetOssimImageLayer.cpp; sourceTree = "<group>"; };
+ 4315BE090C9717B400D36F21 /* ul.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ul.cpp; sourceTree = "<group>"; };
+ 4315BE0A0C9717B400D36F21 /* ulList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ulList.cpp; sourceTree = "<group>"; };
+ 4315BE0B0C9717B400D36F21 /* ossimPlanetLandReaderWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLandReaderWriter.cpp; sourceTree = "<group>"; };
+ 4315BE0C0C9717B400D36F21 /* ossimPlanetLandCullCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLandCullCallback.cpp; sourceTree = "<group>"; };
+ 4315BE0D0C9717B400D36F21 /* ossimPlanetElevationDatabaseGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetElevationDatabaseGroup.cpp; sourceTree = "<group>"; };
+ 4315BE0E0C9717B400D36F21 /* ossimPlanetElevationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetElevationDatabase.cpp; sourceTree = "<group>"; };
+ 4315BE5F0C9717E400D36F21 /* ossimPlanetLandTreeNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandTreeNode.h; sourceTree = "<group>"; };
+ 4315BE600C9717E400D36F21 /* ossimPlanetLandNormalType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandNormalType.h; sourceTree = "<group>"; };
+ 4315BE610C9717E400D36F21 /* ossimPlanetKmlLayerNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKmlLayerNode.h; sourceTree = "<group>"; };
+ 4315BE620C9717E400D36F21 /* netBuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = netBuffer.h; sourceTree = "<group>"; };
+ 4315BE630C9717E400D36F21 /* ossimPlanetLand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLand.h; sourceTree = "<group>"; };
+ 4315BE640C9717E400D36F21 /* ossimPlanetBillboardIcon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetBillboardIcon.h; sourceTree = "<group>"; };
+ 4315BE660C9717E400D36F21 /* ossimPlanetElevationDatabaseGroup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetElevationDatabaseGroup.h; sourceTree = "<group>"; };
+ 4315BE670C9717E400D36F21 /* ossimPlanetIdolLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIdolLayer.h; sourceTree = "<group>"; };
+ 4315BE690C9717E400D36F21 /* ossimPlanetIdManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIdManager.h; sourceTree = "<group>"; };
+ 4315BE6A0C9717E400D36F21 /* ossimPlanetLandReaderWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandReaderWriter.h; sourceTree = "<group>"; };
+ 4315BE6B0C9717E400D36F21 /* ossimPlanetUtility.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetUtility.h; sourceTree = "<group>"; };
+ 4315BE6C0C9717E400D36F21 /* ossimPlanetThreadPool.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetThreadPool.h; sourceTree = "<group>"; };
+ 4315BE6D0C9717E400D36F21 /* ossimPlanetPlaneGrid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPlaneGrid.h; sourceTree = "<group>"; };
+ 4315BE6E0C9717E400D36F21 /* ossimPlanetPagedRequestNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPagedRequestNode.h; sourceTree = "<group>"; };
+ 4315BE6F0C9717E400D36F21 /* ossimPlanetPagedLandLodRefreshType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPagedLandLodRefreshType.h; sourceTree = "<group>"; };
+ 4315BE700C9717E400D36F21 /* ossimPlanetLandNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandNode.h; sourceTree = "<group>"; };
+ 4315BE710C9717E400D36F21 /* ossimPlanetIoSocket.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIoSocket.h; sourceTree = "<group>"; };
+ 4315BE720C9717E400D36F21 /* ossimPlanetInteractionController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetInteractionController.h; sourceTree = "<group>"; };
+ 4315BE730C9717E400D36F21 /* ulLocal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ulLocal.h; sourceTree = "<group>"; };
+ 4315BE740C9717E400D36F21 /* ul.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ul.h; sourceTree = "<group>"; };
+ 4315BE750C9717E400D36F21 /* ossimPlanetInputDevice.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetInputDevice.h; sourceTree = "<group>"; };
+ 4315BE760C9717E400D36F21 /* ossimPlanetShaderProgramSetup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetShaderProgramSetup.h; sourceTree = "<group>"; };
+ 4315BE770C9717E400D36F21 /* ossimPlanetSetup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetSetup.h; sourceTree = "<group>"; };
+ 4315BE780C9717E400D36F21 /* ossimPlanetBoundingBox.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetBoundingBox.h; sourceTree = "<group>"; };
+ 4315BE790C9717E400D36F21 /* ossimPlanetIoSocketServerChannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIoSocketServerChannel.h; sourceTree = "<group>"; };
+ 4315BE7A0C9717E400D36F21 /* ossimPlanetPrimaryBody.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPrimaryBody.h; sourceTree = "<group>"; };
+ 4315BE7B0C9717E400D36F21 /* ossimPlanetSocketNetworkConnection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetSocketNetworkConnection.h; sourceTree = "<group>"; };
+ 4315BE7C0C9717E400D36F21 /* iochannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = iochannel.h; sourceTree = "<group>"; };
+ 4315BE7D0C9717E400D36F21 /* ossimPlanetIconGeom.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIconGeom.h; sourceTree = "<group>"; };
+ 4315BE7E0C9717E400D36F21 /* ossimPlanetTextureLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTextureLayer.h; sourceTree = "<group>"; };
+ 4315BE7F0C9717E400D36F21 /* ossimPlanetTexture2D.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTexture2D.h; sourceTree = "<group>"; };
+ 4315BE800C9717E400D36F21 /* ossimPlanetAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetAction.h; sourceTree = "<group>"; };
+ 4315BE810C9717E400D36F21 /* ossimPlanetServerMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetServerMessageHandler.h; sourceTree = "<group>"; };
+ 4315BE820C9717E400D36F21 /* ossimPlanetSceneView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetSceneView.h; sourceTree = "<group>"; };
+ 4315BE830C9717E400D36F21 /* ossimPlanetManipulator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetManipulator.h; sourceTree = "<group>"; };
+ 4315BE840C9717E400D36F21 /* ossimPlanetWmsImageLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetWmsImageLayer.h; sourceTree = "<group>"; };
+ 4315BE850C9717E400D36F21 /* ossimPlanetThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetThread.h; sourceTree = "<group>"; };
+ 4315BE860C9717E400D36F21 /* ossimPlanetTextureLayerRegistry.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTextureLayerRegistry.h; sourceTree = "<group>"; };
+ 4315BE870C9717E400D36F21 /* netChat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = netChat.h; sourceTree = "<group>"; };
+ 4315BE880C9717E400D36F21 /* ossimPlanetTextureLayerGroup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTextureLayerGroup.h; sourceTree = "<group>"; };
+ 4315BE890C9717E400D36F21 /* ossimPlanetTextureLayerFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTextureLayerFactory.h; sourceTree = "<group>"; };
+ 4315BE8A0C9717E400D36F21 /* ossimPlanetOssimImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetOssimImage.h; sourceTree = "<group>"; };
+ 4315BE8B0C9717E400D36F21 /* ossimPlanetOrthoFlatLandNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetOrthoFlatLandNode.h; sourceTree = "<group>"; };
+ 4315BE8C0C9717E400D36F21 /* ossimPlanetServerThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetServerThread.h; sourceTree = "<group>"; };
+ 4315BE8D0C9717E400D36F21 /* ossimPlanetIoThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIoThread.h; sourceTree = "<group>"; };
+ 4315BE8E0C9717E400D36F21 /* ossimPlanet.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanet.h; sourceTree = "<group>"; };
+ 4315BE8F0C9717E400D36F21 /* ossimPlanetOssimImageLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetOssimImageLayer.h; sourceTree = "<group>"; };
+ 4315BE900C9717E400D36F21 /* ossimPlanetThreadImp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetThreadImp.h; sourceTree = "<group>"; };
+ 4315BE920C9717E400D36F21 /* ossimPlanetLandTextureRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandTextureRequest.h; sourceTree = "<group>"; };
+ 4315BE930C9717E400D36F21 /* ossimPlanetLandCullCallback.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandCullCallback.h; sourceTree = "<group>"; };
+ 4315BE940C9717E400D36F21 /* ossimPlanetConstants.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetConstants.h; sourceTree = "<group>"; };
+ 4315BE950C9717E400D36F21 /* ossimPlanetNetworkConnection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetNetworkConnection.h; sourceTree = "<group>"; };
+ 4315BE960C9717E400D36F21 /* ossimPlanetKml.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKml.h; sourceTree = "<group>"; };
+ 4315BE980C9717E400D36F21 /* ossimPlanetExport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetExport.h; sourceTree = "<group>"; };
+ 4315BE990C9717E400D36F21 /* netMessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = netMessage.h; sourceTree = "<group>"; };
+ 4315BE9A0C9717E400D36F21 /* ossimPlanetIo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIo.h; sourceTree = "<group>"; };
+ 4315BE9B0C9717E400D36F21 /* ossimPlanetJpegImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetJpegImage.h; sourceTree = "<group>"; };
+ 4315BE9C0C9717E400D36F21 /* ossimPlanetLookAt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLookAt.h; sourceTree = "<group>"; };
+ 4315BE9F0C9717E400D36F21 /* net.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = net.h; sourceTree = "<group>"; };
+ 4315BEA00C9717E400D36F21 /* ulRTTI.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ulRTTI.h; sourceTree = "<group>"; };
+ 4315BEA10C9717E400D36F21 /* netChannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = netChannel.h; sourceTree = "<group>"; };
+ 4315BEA20C9717E400D36F21 /* ossimPlanetElevationGrid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetElevationGrid.h; sourceTree = "<group>"; };
+ 4315BEA30C9717E400D36F21 /* ossimPlanetIntersectUserData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIntersectUserData.h; sourceTree = "<group>"; };
+ 4315BEA40C9717E400D36F21 /* ossimPlanetLabelGeom.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLabelGeom.h; sourceTree = "<group>"; };
+ 4315BEA50C9717E400D36F21 /* ossimPlanetGeocoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetGeocoder.h; sourceTree = "<group>"; };
+ 4315BEA60C9717E400D36F21 /* ossimPlanetLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLayer.h; sourceTree = "<group>"; };
+ 4315BEA70C9717E400D36F21 /* netMonitor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = netMonitor.h; sourceTree = "<group>"; };
+ 4315BEA80C9717E400D36F21 /* ossimPlanetId.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetId.h; sourceTree = "<group>"; };
+ 4315BEAA0C9717E400D36F21 /* ossimPlanetActionRouter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetActionRouter.h; sourceTree = "<group>"; };
+ 4315BEAB0C9717E400D36F21 /* ossimPlanetSrtmElevationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetSrtmElevationDatabase.h; sourceTree = "<group>"; };
+ 4315BEAC0C9717E400D36F21 /* ossimPlanetStandardTextureLayerFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetStandardTextureLayerFactory.h; sourceTree = "<group>"; };
+ 4315BEAD0C9717E400D36F21 /* ossimPlanetActionReceiver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetActionReceiver.h; sourceTree = "<group>"; };
+ 4315BEAE0C9717E400D36F21 /* sg_file.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sg_file.h; sourceTree = "<group>"; };
+ 4315BEAF0C9717E400D36F21 /* ossimPlanetYahooGeocoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetYahooGeocoder.h; sourceTree = "<group>"; };
+ 4315BEB00C9717E400D36F21 /* ossimPlanetIoMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIoMessageHandler.h; sourceTree = "<group>"; };
+ 4315BEB10C9717E400D36F21 /* ossimPlanetElevationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetElevationDatabase.h; sourceTree = "<group>"; };
+ 4315BEB20C9717E400D36F21 /* compiler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = compiler.h; sourceTree = "<group>"; };
+ 4315BEB30C9717E400D36F21 /* ossimPlanetLandCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLandCache.h; sourceTree = "<group>"; };
+ 4315BEB40C9717E400D36F21 /* ossimPlanetExtents.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetExtents.h; sourceTree = "<group>"; };
+ 4315BEB50C9717E400D36F21 /* ossimPlanetKmlReaderWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKmlReaderWriter.h; sourceTree = "<group>"; };
+ 4315BEB60C9717E400D36F21 /* ossimPlanetDtedElevationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetDtedElevationDatabase.h; sourceTree = "<group>"; };
+ 4315BEB70C9717E400D36F21 /* ossimPlanetNavigator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetNavigator.h; sourceTree = "<group>"; };
+ 4315BEB80C9717E400D36F21 /* ossimPlanetImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetImage.h; sourceTree = "<group>"; };
+ 4315BEB90C9717E400D36F21 /* sg_socket_udp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sg_socket_udp.h; sourceTree = "<group>"; };
+ 4315BEBA0C9717E400D36F21 /* sg_socket.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sg_socket.h; sourceTree = "<group>"; };
+ 4315BEBB0C9717E400D36F21 /* ossimPlanetCubeGrid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetCubeGrid.h; sourceTree = "<group>"; };
+ 4315BEBC0C9717E400D36F21 /* ossimPlanetIdolBridge.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIdolBridge.h; sourceTree = "<group>"; };
+ 4315BEBE0C9717E400D36F21 /* mkUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mkUtils.h; sourceTree = "<group>"; };
+ 4315BEBF0C9717E400D36F21 /* ossimPlanetLatLonHud.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLatLonHud.h; sourceTree = "<group>"; };
+ 4315BEC00C9717E400D36F21 /* ossimPlanetClientThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetClientThread.h; sourceTree = "<group>"; };
+ 4315BEC10C9717E400D36F21 /* ossimPlanetIoRoutableMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetIoRoutableMessageHandler.h; sourceTree = "<group>"; };
+ 4315BEC20C9717E400D36F21 /* ossimPlanetPagedLandLod.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPagedLandLod.h; sourceTree = "<group>"; };
+ 4315BEC30C9717E400D36F21 /* ossimPlanetWmsClient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetWmsClient.h; sourceTree = "<group>"; };
+ 4315BEC40C9717E400D36F21 /* netSocket.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = netSocket.h; sourceTree = "<group>"; };
+ 4315BEC50C9717E400D36F21 /* ossimPlanetKmlLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKmlLayer.h; sourceTree = "<group>"; };
+ 4315BEC60C9717E400D36F21 /* ossimPlanetGridUtility.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetGridUtility.h; sourceTree = "<group>"; };
+ 4315BEC70C9717E400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetGeneralRasterElevationDatabase.h; sourceTree = "<group>"; };
+ 43244C820F742D70002F5FA3 /* ossimPlanetReentrantMutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetReentrantMutex.h; sourceTree = "<group>"; };
+ 432933BA10FE531E00C66EB8 /* OpenThreads.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenThreads.framework; path = ../../../ossim_dependencies/Frameworks/OpenThreads.framework; sourceTree = SOURCE_ROOT; };
+ 432D60B30CB548C800F15133 /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = "<group>"; };
+ 432D60B40CB548C800F15133 /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; };
+ 432D60B50CB548C800F15133 /* zip.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = "<group>"; };
+ 432D60B90CB548DE00F15133 /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = "<group>"; };
+ 432D60BA0CB548DE00F15133 /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = "<group>"; };
+ 432D60BB0CB548DE00F15133 /* zip.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = "<group>"; };
+ 432FACB80CC4F2D6004D5C1D /* ossimPlanetCallback.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetCallback.h; sourceTree = "<group>"; };
+ 433A4CD8100CED8D000B969C /* ossimplanettest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ossimplanettest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 433A4CF6100CEDD2000B969C /* ossimplanettest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimplanettest.cpp; sourceTree = "<group>"; };
+ 433E7EC10D32B9CF00BA05D0 /* ossimPlanetApi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetApi.h; sourceTree = "<group>"; };
+ 433E7EC70D32B9EC00BA05D0 /* ossimPlanetApi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetApi.cpp; sourceTree = "<group>"; };
+ 4345891B0FD3F95900046CB5 /* ossimPlanetAnimatedPointModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetAnimatedPointModel.cpp; sourceTree = "<group>"; };
+ 4345891D0FD3F96C00046CB5 /* ossimPlanetAnimatedPointModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetAnimatedPointModel.h; sourceTree = "<group>"; };
+ 43463BBF0FCF16DD0027D845 /* ossimPlanetAnimationPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetAnimationPath.h; sourceTree = "<group>"; };
+ 43463BD60FCF78850027D845 /* ossimPlanetAnimationPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetAnimationPath.cpp; sourceTree = "<group>"; };
+ 434E72B810DAACEE005EBB18 /* ossimPlanetOssimElevationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetOssimElevationDatabase.cpp; sourceTree = "<group>"; };
+ 434E72BB10DAAD15005EBB18 /* ossimPlanetOssimElevationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetOssimElevationDatabase.h; sourceTree = "<group>"; };
+ 434EDC170D2BCA2600EDC08A /* ossimPlanetLayerRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLayerRegistry.h; sourceTree = "<group>"; };
+ 434EDC190D2BCC8000EDC08A /* ossimPlanetLayerFactoryBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLayerFactoryBase.h; sourceTree = "<group>"; };
+ 434EDC3B0D2BD04400EDC08A /* ossimPlanetLayerFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLayerFactory.h; sourceTree = "<group>"; };
+ 434EDC3E0D2BD20500EDC08A /* ossimPlanetLayerRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLayerRegistry.cpp; sourceTree = "<group>"; };
+ 434EDC7A0D2BD8D200EDC08A /* ossimPlanetLayerFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLayerFactory.cpp; sourceTree = "<group>"; };
+ 4351096D0FCC130A0065BA0E /* ossimPlanetViewMatrixBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetViewMatrixBuilder.h; sourceTree = "<group>"; };
+ 435109730FCC134C0065BA0E /* ossimPlanetViewMatrixBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPlanetViewMatrixBuilder.cpp; path = ../../src/ossimPlanet/ossimPlanetViewMatrixBuilder.cpp; sourceTree = SOURCE_ROOT; };
+ 435BD1FB0F09848100CEAEAD /* ossimPlanetViewer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetViewer.h; sourceTree = "<group>"; };
+ 43669A920CD177A400F1832B /* ossimPlanetSousaLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetSousaLayer.h; sourceTree = "<group>"; };
+ 43669A940CD177CD00F1832B /* ossimPlanetSousaLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetSousaLayer.cpp; sourceTree = "<group>"; };
+ 4377D4271029BB5800B6652D /* ossimPlanetCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetCache.h; sourceTree = "<group>"; };
+ 4377D4291029BB7000B6652D /* ossimPlanetCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetCache.cpp; sourceTree = "<group>"; };
+ 4377D6F7102C509900B6652D /* ossimPlanetKmlNetworkLinkNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetKmlNetworkLinkNode.cpp; sourceTree = "<group>"; };
+ 4377D6FA102C50AD00B6652D /* ossimPlanetKmlNetworkLinkNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKmlNetworkLinkNode.h; sourceTree = "<group>"; };
+ 437D9DE60FC3FFA60018F889 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
+ 43A113940D520D5D00DE3CF3 /* ossimPlanetNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetNode.cpp; sourceTree = "<group>"; };
+ 43A113970D520D7100DE3CF3 /* ossimPlanetNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetNode.h; sourceTree = "<group>"; };
+ 43A113DC0D520F3600DE3CF3 /* ossimPlanetNodeFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetNodeFactory.h; sourceTree = "<group>"; };
+ 43A113DD0D520F3600DE3CF3 /* ossimPlanetNodeRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetNodeRegistry.h; sourceTree = "<group>"; };
+ 43A113DE0D520F3600DE3CF3 /* ossimPlanetNodeFactoryBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetNodeFactoryBase.h; sourceTree = "<group>"; };
+ 43A113E50D520F8900DE3CF3 /* ossimPlanetNodeFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetNodeFactory.cpp; sourceTree = "<group>"; };
+ 43A113E60D520F8900DE3CF3 /* ossimPlanetNodeRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetNodeRegistry.cpp; sourceTree = "<group>"; };
+ 43A52F140D4FA87100DB4777 /* ossimPlanetVisitors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetVisitors.cpp; sourceTree = "<group>"; };
+ 43AA128E0D77ADF90020DF13 /* ossimPlanetXmlAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetXmlAction.cpp; sourceTree = "<group>"; };
+ 43AB5FAE0FF99226004874C2 /* ossimPlanetEphemeris.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetEphemeris.h; sourceTree = "<group>"; };
+ 43AB5FB20FF99240004874C2 /* ossimPlanetEphemeris.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetEphemeris.cpp; sourceTree = "<group>"; };
+ 43BC2F8C0F8D13A600838B40 /* ossimPlanetTileRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTileRequest.cpp; sourceTree = "<group>"; };
+ 43BC2F8E0F8D13C600838B40 /* ossimPlanetTileRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTileRequest.h; sourceTree = "<group>"; };
+ 43C443DD0D4A2179004BDD99 /* ossimPlanetOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetOperation.h; sourceTree = "<group>"; };
+ 43C443E10D4A2C6D004BDD99 /* ossimPlanetOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetOperation.cpp; sourceTree = "<group>"; };
+ 43C6E2910FEFB4D8004B52F7 /* ossimplanetklv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ossimplanetklv; sourceTree = BUILT_PRODUCTS_DIR; };
+ 43C6E29C0FEFB4E9004B52F7 /* ossimplanetviewer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ossimplanetviewer; sourceTree = BUILT_PRODUCTS_DIR; };
+ 43C6E2B60FEFB50E004B52F7 /* ossimplanetklv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimplanetklv.cpp; sourceTree = "<group>"; };
+ 43C6E2C30FEFB531004B52F7 /* ossimplanetviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimplanetviewer.cpp; sourceTree = "<group>"; };
+ 43C6E2C50FEFB531004B52F7 /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = "<group>"; };
+ 43C8A82D0CAACB4E00EE840F /* ossimPlanetKmlPlacemarkNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetKmlPlacemarkNode.h; sourceTree = "<group>"; };
+ 43C8A8310CAACB6500EE840F /* ossimPlanetKmlPlacemarkNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetKmlPlacemarkNode.cpp; sourceTree = "<group>"; };
+ 43CA034C0DD34451003EC1AB /* ossimPlanetArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetArchive.h; sourceTree = "<group>"; };
+ 43CA034D0DD34451003EC1AB /* ossimPlanetArchiveMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetArchiveMapping.h; sourceTree = "<group>"; };
+ 43CA03500DD34464003EC1AB /* ossimPlanetArchiveMapping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetArchiveMapping.cpp; sourceTree = "<group>"; };
+ 43CA03510DD34464003EC1AB /* ossimPlanetArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetArchive.cpp; sourceTree = "<group>"; };
+ 43D65A300F6839F1006C6786 /* ossimPlanetTerrainLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTerrainLayer.h; sourceTree = "<group>"; };
+ 43D65A520F683B15006C6786 /* ossimPlanetTerrainLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTerrainLayer.cpp; sourceTree = "<group>"; };
+ 43D7ECB210FE1F8500762FA7 /* gpstk.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = gpstk.framework; path = ../../../ossim_dependencies/Frameworks/gpstk.framework; sourceTree = SOURCE_ROOT; };
+ 43D8A1080D818E2200A60690 /* ossimPlanet.xsd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = ossimPlanet.xsd; path = ../../schema/ossimPlanet.xsd; sourceTree = SOURCE_ROOT; };
+ 43D8A1120D818ED300A60690 /* binds.act */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = binds.act; path = ../../binds.act; sourceTree = SOURCE_ROOT; };
+ 43D9C7DF10A4BBB900BA9119 /* ossimPlanetCacheTextureLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetCacheTextureLayer.cpp; sourceTree = "<group>"; };
+ 43D9C7E410A4BC0F00BA9119 /* ossimPlanetCacheTextureLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetCacheTextureLayer.h; sourceTree = "<group>"; };
+ 43E957DF0D2931C000D31E60 /* ossimPlanetRefBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetRefBlock.h; sourceTree = "<group>"; };
+ 43FDA2D60D770D0700945FA0 /* ossimPlanetDestinationCommandAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetDestinationCommandAction.h; sourceTree = "<group>"; };
+ 43FDA2D90D77274F00945FA0 /* ossimPlanetDestinationCommandAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetDestinationCommandAction.cpp; sourceTree = "<group>"; };
+ 43FDA3D20D77495200945FA0 /* ossimPlanetXmlAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetXmlAction.h; sourceTree = "<group>"; };
+ 43FF0C1F1021065500CEA135 /* ossimPlanetCloudLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetCloudLayer.h; sourceTree = "<group>"; };
+ 43FF0C251021068E00CEA135 /* ossimPlanetCloudLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetCloudLayer.cpp; sourceTree = "<group>"; };
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 8D07F2C80486CC7A007CD1D0 /* ossimPlanet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ossimPlanet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ EE0517BB0EE81BB6009EC91D /* ossimPlanetViewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetViewer.cpp; sourceTree = "<group>"; };
+ EE26B2390F39CB8400D4028C /* ossimPlanetElevationRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetElevationRegistry.h; sourceTree = "<group>"; };
+ EE26B23C0F39CC0D00D4028C /* ossimPlanetElevationRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetElevationRegistry.cpp; sourceTree = "<group>"; };
+ EE26B2670F39DD1100D4028C /* ossimPlanetElevationFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetElevationFactory.cpp; sourceTree = "<group>"; };
+ EE26B2690F39DD2000D4028C /* ossimPlanetElevationFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetElevationFactory.h; sourceTree = "<group>"; };
+ EE2F90FC0EB5E188003D424A /* ossimPlanetMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetMessage.h; sourceTree = "<group>"; };
+ EE5403640F5D7030001139DD /* ossimPlanetTerrain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTerrain.cpp; sourceTree = "<group>"; };
+ EE5403660F5D7041001139DD /* ossimPlanetTerrain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTerrain.h; sourceTree = "<group>"; };
+ EE5403690F5D74F5001139DD /* ossimPlanetTerrainTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTerrainTile.h; sourceTree = "<group>"; };
+ EE5403780F5D7522001139DD /* ossimPlanetTerrainTile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTerrainTile.cpp; sourceTree = "<group>"; };
+ EE5403EA0F5D8C42001139DD /* ossimPlanetGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetGrid.cpp; sourceTree = "<group>"; };
+ EE5403ED0F5D8C50001139DD /* ossimPlanetGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetGrid.h; sourceTree = "<group>"; };
+ EE5403F00F5D8DDE001139DD /* ossimPlanetTerrainTileId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTerrainTileId.h; sourceTree = "<group>"; };
+ EE5404540F5E21CF001139DD /* ossimPlanetTerrainTechnique.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTerrainTechnique.cpp; sourceTree = "<group>"; };
+ EE5404560F5E21DD001139DD /* ossimPlanetTerrainTechnique.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTerrainTechnique.h; sourceTree = "<group>"; };
+ EE5404590F5E24D2001139DD /* ossimPlanetTerrainGeometryTechnique.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetTerrainGeometryTechnique.h; sourceTree = "<group>"; };
+ EE5404650F5E24EC001139DD /* ossimPlanetTerrainGeometryTechnique.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetTerrainGeometryTechnique.cpp; sourceTree = "<group>"; };
+ EE5409A00F615143001139DD /* ossimPlanetPointModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetPointModel.cpp; sourceTree = "<group>"; };
+ EE5409A20F61516D001139DD /* ossimPlanetPointModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPointModel.h; sourceTree = "<group>"; };
+ EE540A8E0F61A503001139DD /* ossimPlanetGeoRefModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetGeoRefModel.h; sourceTree = "<group>"; };
+ EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libwms.xcodeproj; path = ../../../libwms/xcode/libwms/libwms.xcodeproj; sourceTree = SOURCE_ROOT; };
+ EE9B0A4C0F6463A500394285 /* ossimPlanetLsrSpaceTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetLsrSpaceTransform.h; sourceTree = "<group>"; };
+ EE9B0A6F0F6463C400394285 /* ossimPlanetLsrSpaceTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetLsrSpaceTransform.cpp; sourceTree = "<group>"; };
+ EEB5ECD80D0F214E000CF6B2 /* ossimPlanetVideoLayer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetVideoLayer.h; sourceTree = "<group>"; };
+ EEB5ECE40D0F220C000CF6B2 /* ossimPlanetVideoLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetVideoLayer.cpp; sourceTree = "<group>"; };
+ EEB5ECEC0D0F2284000CF6B2 /* ossimPredator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ossimPredator.xcodeproj; path = ../../../ossimPredator/xcode/ossimPredator/ossimPredator.xcodeproj; sourceTree = SOURCE_ROOT; };
+ EEB5EDDB0D101235000CF6B2 /* ossimPlanetPredatorVideoLayerNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetPredatorVideoLayerNode.cpp; sourceTree = "<group>"; };
+ EEB5EDDD0D101268000CF6B2 /* ossimPlanetPredatorVideoLayerNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetPredatorVideoLayerNode.h; sourceTree = "<group>"; };
+ EEBDD68D0D464823009DB3D5 /* ossimPlanetAnnotationLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetAnnotationLayer.h; sourceTree = "<group>"; };
+ EEBDD6900D465A0B009DB3D5 /* ossimPlanetAnnotationLayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetAnnotationLayer.cpp; sourceTree = "<group>"; };
+ EEBDD6CB0D46E214009DB3D5 /* ossimPlanetAnnotationLayerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetAnnotationLayerNode.h; sourceTree = "<group>"; };
+ EEBDD6CE0D46E3AC009DB3D5 /* ossimPlanetAnnotationLayerNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetAnnotationLayerNode.cpp; sourceTree = "<group>"; };
+ EEBDDA790D491078009DB3D5 /* ossimPlanetVideoLayerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimPlanetVideoLayerNode.h; sourceTree = "<group>"; };
+ EED173950CA0174100DF3588 /* ossimPlanetFadeText.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimPlanetFadeText.h; sourceTree = "<group>"; };
+ EED173970CA0174E00DF3588 /* ossimPlanetFadeText.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimPlanetFadeText.cpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 433A4CC9100CED8D000B969C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4329352F10FE591500C66EB8 /* osgText.framework in Frameworks */,
+ 4329351A10FE57FA00C66EB8 /* OpenThreads.framework in Frameworks */,
+ 4329351B10FE57FA00C66EB8 /* osgDB.framework in Frameworks */,
+ 4329351C10FE57FA00C66EB8 /* osgUtil.framework in Frameworks */,
+ 4329351D10FE57FA00C66EB8 /* osgViewer.framework in Frameworks */,
+ 4329351E10FE57FA00C66EB8 /* osgGA.framework in Frameworks */,
+ 4329351F10FE57FA00C66EB8 /* osg.framework in Frameworks */,
+ 433A4CCA100CED8D000B969C /* ossim.framework in Frameworks */,
+ 433A4CCF100CED8D000B969C /* ossimPlanet.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 43C6E28F0FEFB4D8004B52F7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 432933E410FE579100C66EB8 /* osg.framework in Frameworks */,
+ 432933E110FE577D00C66EB8 /* OpenThreads.framework in Frameworks */,
+ 43AB5F570FF9434D004874C2 /* ossim.framework in Frameworks */,
+ 43C6E2CB0FEFB572004B52F7 /* ossimPredator.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 43C6E29A0FEFB4E9004B52F7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 432934CA10FE57D600C66EB8 /* osgDB.framework in Frameworks */,
+ 432934C510FE57C800C66EB8 /* OpenThreads.framework in Frameworks */,
+ 432934C210FE57AF00C66EB8 /* osg.framework in Frameworks */,
+ 432934AB10FE57AC00C66EB8 /* osgGA.framework in Frameworks */,
+ 4329349110FE57A200C66EB8 /* osgViewer.framework in Frameworks */,
+ 43C6E5660FF00474004B52F7 /* ossim.framework in Frameworks */,
+ 43C6E2CC0FEFB580004B52F7 /* ossimPlanet.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EEB5ECF20D0F2292000CF6B2 /* ossimPredator.framework in Frameworks */,
+ EE69A3550B28842B00C91DD1 /* wms.framework in Frameworks */,
+ 186EF5700B1CE22D00F7886A /* ossim.framework in Frameworks */,
+ 437D9DE70FC3FFA60018F889 /* OpenGL.framework in Frameworks */,
+ 4306ABAB10FE11A700C7202A /* osg.framework in Frameworks */,
+ 4306ABAD10FE11AC00C7202A /* osgGA.framework in Frameworks */,
+ 4306ABB210FE11C000C7202A /* osgDB.framework in Frameworks */,
+ 4306ABB310FE11C000C7202A /* osgText.framework in Frameworks */,
+ 4306ABB410FE11C000C7202A /* osgUtil.framework in Frameworks */,
+ 4306ABB510FE11C000C7202A /* osgViewer.framework in Frameworks */,
+ 43D7ECB310FE1F8500762FA7 /* gpstk.framework in Frameworks */,
+ 432933BB10FE531E00C66EB8 /* OpenThreads.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C80486CC7A007CD1D0 /* ossimPlanet.framework */,
+ 43C6E2910FEFB4D8004B52F7 /* ossimplanetklv */,
+ 43C6E29C0FEFB4E9004B52F7 /* ossimplanetviewer */,
+ 433A4CD8100CED8D000B969C /* ossimplanettest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* ossimPlanet */ = {
+ isa = PBXGroup;
+ children = (
+ EE9D25F30DD87952005A8951 /* apps */,
+ 43D8A10D0D818EC100A60690 /* Sample files */,
+ 43D8A1060D818DFD00A60690 /* schema */,
+ 08FB77ACFE841707C02AAC07 /* Source */,
+ 089C1665FE841158C02AAC07 /* Resources */,
+ 1862497F0B2070A20021FDF7 /* External Projects */,
+ 437D9ACC0FC3FE810018F889 /* External Frameworks and Libraries */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = ossimPlanet;
+ sourceTree = "<group>";
+ };
+ 089C1665FE841158C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */,
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 08FB77ACFE841707C02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */,
+ 186EECB10B1CDF1400F7886A /* ossimPlanet */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1862497F0B2070A20021FDF7 /* External Projects */ = {
+ isa = PBXGroup;
+ children = (
+ 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */,
+ EEB5ECEC0D0F2284000CF6B2 /* ossimPredator.xcodeproj */,
+ EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */,
+ );
+ name = "External Projects";
+ sourceTree = "<group>";
+ };
+ 186EECB10B1CDF1400F7886A /* ossimPlanet */ = {
+ isa = PBXGroup;
+ children = (
+ 186EECB20B1CDF1400F7886A /* include */,
+ 186EECF10B1CDF1400F7886A /* src */,
+ );
+ name = ossimPlanet;
+ path = ../..;
+ sourceTree = SOURCE_ROOT;
+ };
+ 186EECB20B1CDF1400F7886A /* include */ = {
+ isa = PBXGroup;
+ children = (
+ 186EECB30B1CDF1400F7886A /* ossimPlanet */,
+ );
+ path = include;
+ sourceTree = "<group>";
+ };
+ 186EECB30B1CDF1400F7886A /* ossimPlanet */ = {
+ isa = PBXGroup;
+ children = (
+ 430D8E931100DA5200EB0F96 /* ossimPlanetDistanceAccumulator.h */,
+ 430D8E901100DA3F00EB0F96 /* ossimPlanetDepthPartitionNode.h */,
+ 434E72BB10DAAD15005EBB18 /* ossimPlanetOssimElevationDatabase.h */,
+ 43D9C7E410A4BC0F00BA9119 /* ossimPlanetCacheTextureLayer.h */,
+ 4377D6FA102C50AD00B6652D /* ossimPlanetKmlNetworkLinkNode.h */,
+ 4377D4271029BB5800B6652D /* ossimPlanetCache.h */,
+ 43FF0C1F1021065500CEA135 /* ossimPlanetCloudLayer.h */,
+ 43AB5FAE0FF99226004874C2 /* ossimPlanetEphemeris.h */,
+ 4345891D0FD3F96C00046CB5 /* ossimPlanetAnimatedPointModel.h */,
+ 43463BBF0FCF16DD0027D845 /* ossimPlanetAnimationPath.h */,
+ 435109730FCC134C0065BA0E /* ossimPlanetViewMatrixBuilder.cpp */,
+ 4351096D0FCC130A0065BA0E /* ossimPlanetViewMatrixBuilder.h */,
+ 43BC2F8E0F8D13C600838B40 /* ossimPlanetTileRequest.h */,
+ 43244C820F742D70002F5FA3 /* ossimPlanetReentrantMutex.h */,
+ 43D65A300F6839F1006C6786 /* ossimPlanetTerrainLayer.h */,
+ EE9B0A4C0F6463A500394285 /* ossimPlanetLsrSpaceTransform.h */,
+ EE540A8E0F61A503001139DD /* ossimPlanetGeoRefModel.h */,
+ EE5409A20F61516D001139DD /* ossimPlanetPointModel.h */,
+ EE5404590F5E24D2001139DD /* ossimPlanetTerrainGeometryTechnique.h */,
+ EE5404560F5E21DD001139DD /* ossimPlanetTerrainTechnique.h */,
+ EE5403F00F5D8DDE001139DD /* ossimPlanetTerrainTileId.h */,
+ EE5403ED0F5D8C50001139DD /* ossimPlanetGrid.h */,
+ EE5403690F5D74F5001139DD /* ossimPlanetTerrainTile.h */,
+ EE5403660F5D7041001139DD /* ossimPlanetTerrain.h */,
+ 430485FD0F3CB80800B9C1E2 /* ossimPlanetDatabasePager.h */,
+ EE26B2690F39DD2000D4028C /* ossimPlanetElevationFactory.h */,
+ EE26B2390F39CB8400D4028C /* ossimPlanetElevationRegistry.h */,
+ 435BD1FB0F09848100CEAEAD /* ossimPlanetViewer.h */,
+ EE2F90FC0EB5E188003D424A /* ossimPlanetMessage.h */,
+ 43CA034C0DD34451003EC1AB /* ossimPlanetArchive.h */,
+ 43CA034D0DD34451003EC1AB /* ossimPlanetArchiveMapping.h */,
+ 43A113DC0D520F3600DE3CF3 /* ossimPlanetNodeFactory.h */,
+ 43A113DD0D520F3600DE3CF3 /* ossimPlanetNodeRegistry.h */,
+ 43A113DE0D520F3600DE3CF3 /* ossimPlanetNodeFactoryBase.h */,
+ 43A113970D520D7100DE3CF3 /* ossimPlanetNode.h */,
+ 43C443DD0D4A2179004BDD99 /* ossimPlanetOperation.h */,
+ EEBDDA790D491078009DB3D5 /* ossimPlanetVideoLayerNode.h */,
+ EEBDD6CB0D46E214009DB3D5 /* ossimPlanetAnnotationLayerNode.h */,
+ EEBDD68D0D464823009DB3D5 /* ossimPlanetAnnotationLayer.h */,
+ 433E7EC10D32B9CF00BA05D0 /* ossimPlanetApi.h */,
+ 434EDC3B0D2BD04400EDC08A /* ossimPlanetLayerFactory.h */,
+ 434EDC190D2BCC8000EDC08A /* ossimPlanetLayerFactoryBase.h */,
+ 434EDC170D2BCA2600EDC08A /* ossimPlanetLayerRegistry.h */,
+ 43E957DF0D2931C000D31E60 /* ossimPlanetRefBlock.h */,
+ EEB5EDDD0D101268000CF6B2 /* ossimPlanetPredatorVideoLayerNode.h */,
+ EEB5ECD80D0F214E000CF6B2 /* ossimPlanetVideoLayer.h */,
+ 43669A920CD177A400F1832B /* ossimPlanetSousaLayer.h */,
+ 432FACB80CC4F2D6004D5C1D /* ossimPlanetCallback.h */,
+ 4314728E0CBE9F0F00EAADAB /* ossimPlanetVisitors.h */,
+ 430C8F680CBBD0CA002BAF12 /* ossimPlanetCompass.h */,
+ 432D60B90CB548DE00F15133 /* ioapi.h */,
+ 432D60BA0CB548DE00F15133 /* unzip.h */,
+ 432D60BB0CB548DE00F15133 /* zip.h */,
+ 43C8A82D0CAACB4E00EE840F /* ossimPlanetKmlPlacemarkNode.h */,
+ 431476560CA838400090B3CE /* ossimPlanetKmlScreenOverlayNode.h */,
+ EED173950CA0174100DF3588 /* ossimPlanetFadeText.h */,
+ 4315BE5F0C9717E400D36F21 /* ossimPlanetLandTreeNode.h */,
+ 4315BE600C9717E400D36F21 /* ossimPlanetLandNormalType.h */,
+ 4315BE610C9717E400D36F21 /* ossimPlanetKmlLayerNode.h */,
+ 4315BE620C9717E400D36F21 /* netBuffer.h */,
+ 4315BE630C9717E400D36F21 /* ossimPlanetLand.h */,
+ 4315BE640C9717E400D36F21 /* ossimPlanetBillboardIcon.h */,
+ 4315BE660C9717E400D36F21 /* ossimPlanetElevationDatabaseGroup.h */,
+ 4315BE670C9717E400D36F21 /* ossimPlanetIdolLayer.h */,
+ 4315BE690C9717E400D36F21 /* ossimPlanetIdManager.h */,
+ 4315BE6A0C9717E400D36F21 /* ossimPlanetLandReaderWriter.h */,
+ 4315BE6B0C9717E400D36F21 /* ossimPlanetUtility.h */,
+ 4315BE6C0C9717E400D36F21 /* ossimPlanetThreadPool.h */,
+ 4315BE6D0C9717E400D36F21 /* ossimPlanetPlaneGrid.h */,
+ 4315BE6E0C9717E400D36F21 /* ossimPlanetPagedRequestNode.h */,
+ 4315BE6F0C9717E400D36F21 /* ossimPlanetPagedLandLodRefreshType.h */,
+ 4315BE700C9717E400D36F21 /* ossimPlanetLandNode.h */,
+ 4315BE710C9717E400D36F21 /* ossimPlanetIoSocket.h */,
+ 4315BE720C9717E400D36F21 /* ossimPlanetInteractionController.h */,
+ 4315BE730C9717E400D36F21 /* ulLocal.h */,
+ 4315BE740C9717E400D36F21 /* ul.h */,
+ 4315BE750C9717E400D36F21 /* ossimPlanetInputDevice.h */,
+ 4315BE760C9717E400D36F21 /* ossimPlanetShaderProgramSetup.h */,
+ 4315BE770C9717E400D36F21 /* ossimPlanetSetup.h */,
+ 4315BE780C9717E400D36F21 /* ossimPlanetBoundingBox.h */,
+ 4315BE8F0C9717E400D36F21 /* ossimPlanetOssimImageLayer.h */,
+ 4315BE790C9717E400D36F21 /* ossimPlanetIoSocketServerChannel.h */,
+ 4315BE7A0C9717E400D36F21 /* ossimPlanetPrimaryBody.h */,
+ 4315BE7B0C9717E400D36F21 /* ossimPlanetSocketNetworkConnection.h */,
+ 4315BE7C0C9717E400D36F21 /* iochannel.h */,
+ 4315BE7D0C9717E400D36F21 /* ossimPlanetIconGeom.h */,
+ 4315BE7E0C9717E400D36F21 /* ossimPlanetTextureLayer.h */,
+ 4315BE7F0C9717E400D36F21 /* ossimPlanetTexture2D.h */,
+ 4315BE800C9717E400D36F21 /* ossimPlanetAction.h */,
+ 4315BE810C9717E400D36F21 /* ossimPlanetServerMessageHandler.h */,
+ 4315BE820C9717E400D36F21 /* ossimPlanetSceneView.h */,
+ 4315BE830C9717E400D36F21 /* ossimPlanetManipulator.h */,
+ 4315BE840C9717E400D36F21 /* ossimPlanetWmsImageLayer.h */,
+ 4315BE850C9717E400D36F21 /* ossimPlanetThread.h */,
+ 4315BE860C9717E400D36F21 /* ossimPlanetTextureLayerRegistry.h */,
+ 4315BE870C9717E400D36F21 /* netChat.h */,
+ 4315BE880C9717E400D36F21 /* ossimPlanetTextureLayerGroup.h */,
+ 4315BE890C9717E400D36F21 /* ossimPlanetTextureLayerFactory.h */,
+ 4315BE8A0C9717E400D36F21 /* ossimPlanetOssimImage.h */,
+ 4315BE8B0C9717E400D36F21 /* ossimPlanetOrthoFlatLandNode.h */,
+ 4315BE8C0C9717E400D36F21 /* ossimPlanetServerThread.h */,
+ 4315BE8D0C9717E400D36F21 /* ossimPlanetIoThread.h */,
+ 4315BE8E0C9717E400D36F21 /* ossimPlanet.h */,
+ 4315BE900C9717E400D36F21 /* ossimPlanetThreadImp.h */,
+ 4315BE920C9717E400D36F21 /* ossimPlanetLandTextureRequest.h */,
+ 4315BE930C9717E400D36F21 /* ossimPlanetLandCullCallback.h */,
+ 4315BE940C9717E400D36F21 /* ossimPlanetConstants.h */,
+ 4315BE950C9717E400D36F21 /* ossimPlanetNetworkConnection.h */,
+ 4315BE960C9717E400D36F21 /* ossimPlanetKml.h */,
+ 4315BE980C9717E400D36F21 /* ossimPlanetExport.h */,
+ 4315BE990C9717E400D36F21 /* netMessage.h */,
+ 4315BE9A0C9717E400D36F21 /* ossimPlanetIo.h */,
+ 4315BE9B0C9717E400D36F21 /* ossimPlanetJpegImage.h */,
+ 4315BE9C0C9717E400D36F21 /* ossimPlanetLookAt.h */,
+ 4315BE9F0C9717E400D36F21 /* net.h */,
+ 4315BEA00C9717E400D36F21 /* ulRTTI.h */,
+ 4315BEA10C9717E400D36F21 /* netChannel.h */,
+ 4315BEA20C9717E400D36F21 /* ossimPlanetElevationGrid.h */,
+ 4315BEA30C9717E400D36F21 /* ossimPlanetIntersectUserData.h */,
+ 4315BEA40C9717E400D36F21 /* ossimPlanetLabelGeom.h */,
+ 4315BEA50C9717E400D36F21 /* ossimPlanetGeocoder.h */,
+ 4315BEA60C9717E400D36F21 /* ossimPlanetLayer.h */,
+ 4315BEA70C9717E400D36F21 /* netMonitor.h */,
+ 4315BEA80C9717E400D36F21 /* ossimPlanetId.h */,
+ 4315BEAA0C9717E400D36F21 /* ossimPlanetActionRouter.h */,
+ 4315BEAB0C9717E400D36F21 /* ossimPlanetSrtmElevationDatabase.h */,
+ 4315BEAC0C9717E400D36F21 /* ossimPlanetStandardTextureLayerFactory.h */,
+ 4315BEAD0C9717E400D36F21 /* ossimPlanetActionReceiver.h */,
+ 4315BEAE0C9717E400D36F21 /* sg_file.h */,
+ 4315BEAF0C9717E400D36F21 /* ossimPlanetYahooGeocoder.h */,
+ 4315BEB00C9717E400D36F21 /* ossimPlanetIoMessageHandler.h */,
+ 4315BEB10C9717E400D36F21 /* ossimPlanetElevationDatabase.h */,
+ 4315BEB20C9717E400D36F21 /* compiler.h */,
+ 4315BEB30C9717E400D36F21 /* ossimPlanetLandCache.h */,
+ 4315BEB40C9717E400D36F21 /* ossimPlanetExtents.h */,
+ 4315BEB50C9717E400D36F21 /* ossimPlanetKmlReaderWriter.h */,
+ 4315BEB60C9717E400D36F21 /* ossimPlanetDtedElevationDatabase.h */,
+ 4315BEB70C9717E400D36F21 /* ossimPlanetNavigator.h */,
+ 4315BEB80C9717E400D36F21 /* ossimPlanetImage.h */,
+ 4315BEB90C9717E400D36F21 /* sg_socket_udp.h */,
+ 4315BEBA0C9717E400D36F21 /* sg_socket.h */,
+ 4315BEBB0C9717E400D36F21 /* ossimPlanetCubeGrid.h */,
+ 4315BEBC0C9717E400D36F21 /* ossimPlanetIdolBridge.h */,
+ 4315BEBE0C9717E400D36F21 /* mkUtils.h */,
+ 4315BEBF0C9717E400D36F21 /* ossimPlanetLatLonHud.h */,
+ 4315BEC00C9717E400D36F21 /* ossimPlanetClientThread.h */,
+ 4315BEC10C9717E400D36F21 /* ossimPlanetIoRoutableMessageHandler.h */,
+ 4315BEC20C9717E400D36F21 /* ossimPlanetPagedLandLod.h */,
+ 4315BEC30C9717E400D36F21 /* ossimPlanetWmsClient.h */,
+ 4315BEC40C9717E400D36F21 /* netSocket.h */,
+ 4315BEC50C9717E400D36F21 /* ossimPlanetKmlLayer.h */,
+ 4315BEC60C9717E400D36F21 /* ossimPlanetGridUtility.h */,
+ 4315BEC70C9717E400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.h */,
+ 43FDA2D60D770D0700945FA0 /* ossimPlanetDestinationCommandAction.h */,
+ 43FDA3D20D77495200945FA0 /* ossimPlanetXmlAction.h */,
+ );
+ path = ossimPlanet;
+ sourceTree = "<group>";
+ };
+ 186EECF10B1CDF1400F7886A /* src */ = {
+ isa = PBXGroup;
+ children = (
+ 186EECF20B1CDF1400F7886A /* ossimPlanet */,
+ );
+ path = src;
+ sourceTree = "<group>";
+ };
+ 186EECF20B1CDF1400F7886A /* ossimPlanet */ = {
+ isa = PBXGroup;
+ children = (
+ 430D8E971100DB1F00EB0F96 /* ossimPlanetDepthPartitionNode.cpp */,
+ 430D8E981100DB1F00EB0F96 /* ossimPlanetDistanceAccumulator.cpp */,
+ 434E72B810DAACEE005EBB18 /* ossimPlanetOssimElevationDatabase.cpp */,
+ 43D9C7DF10A4BBB900BA9119 /* ossimPlanetCacheTextureLayer.cpp */,
+ 4377D6F7102C509900B6652D /* ossimPlanetKmlNetworkLinkNode.cpp */,
+ 4377D4291029BB7000B6652D /* ossimPlanetCache.cpp */,
+ 43FF0C251021068E00CEA135 /* ossimPlanetCloudLayer.cpp */,
+ 43AB5FB20FF99240004874C2 /* ossimPlanetEphemeris.cpp */,
+ 4345891B0FD3F95900046CB5 /* ossimPlanetAnimatedPointModel.cpp */,
+ 43463BD60FCF78850027D845 /* ossimPlanetAnimationPath.cpp */,
+ 43BC2F8C0F8D13A600838B40 /* ossimPlanetTileRequest.cpp */,
+ 43D65A520F683B15006C6786 /* ossimPlanetTerrainLayer.cpp */,
+ EE9B0A6F0F6463C400394285 /* ossimPlanetLsrSpaceTransform.cpp */,
+ EE5409A00F615143001139DD /* ossimPlanetPointModel.cpp */,
+ EE5404650F5E24EC001139DD /* ossimPlanetTerrainGeometryTechnique.cpp */,
+ EE5404540F5E21CF001139DD /* ossimPlanetTerrainTechnique.cpp */,
+ EE5403EA0F5D8C42001139DD /* ossimPlanetGrid.cpp */,
+ EE5403780F5D7522001139DD /* ossimPlanetTerrainTile.cpp */,
+ EE5403640F5D7030001139DD /* ossimPlanetTerrain.cpp */,
+ EE26B2670F39DD1100D4028C /* ossimPlanetElevationFactory.cpp */,
+ EE26B23C0F39CC0D00D4028C /* ossimPlanetElevationRegistry.cpp */,
+ EE0517BB0EE81BB6009EC91D /* ossimPlanetViewer.cpp */,
+ 43CA03500DD34464003EC1AB /* ossimPlanetArchiveMapping.cpp */,
+ 43CA03510DD34464003EC1AB /* ossimPlanetArchive.cpp */,
+ 43A113E50D520F8900DE3CF3 /* ossimPlanetNodeFactory.cpp */,
+ 43A113E60D520F8900DE3CF3 /* ossimPlanetNodeRegistry.cpp */,
+ 43A113940D520D5D00DE3CF3 /* ossimPlanetNode.cpp */,
+ 43A52F140D4FA87100DB4777 /* ossimPlanetVisitors.cpp */,
+ 43C443E10D4A2C6D004BDD99 /* ossimPlanetOperation.cpp */,
+ EEBDD6CE0D46E3AC009DB3D5 /* ossimPlanetAnnotationLayerNode.cpp */,
+ EEBDD6900D465A0B009DB3D5 /* ossimPlanetAnnotationLayer.cpp */,
+ 433E7EC70D32B9EC00BA05D0 /* ossimPlanetApi.cpp */,
+ 434EDC7A0D2BD8D200EDC08A /* ossimPlanetLayerFactory.cpp */,
+ 434EDC3E0D2BD20500EDC08A /* ossimPlanetLayerRegistry.cpp */,
+ EEB5EDDB0D101235000CF6B2 /* ossimPlanetPredatorVideoLayerNode.cpp */,
+ EEB5ECE40D0F220C000CF6B2 /* ossimPlanetVideoLayer.cpp */,
+ 43669A940CD177CD00F1832B /* ossimPlanetSousaLayer.cpp */,
+ 430C8F660CBBD0B8002BAF12 /* ossimPlanetCompass.cpp */,
+ 432D60B30CB548C800F15133 /* ioapi.c */,
+ 432D60B40CB548C800F15133 /* unzip.c */,
+ 432D60B50CB548C800F15133 /* zip.c */,
+ 43C8A8310CAACB6500EE840F /* ossimPlanetKmlPlacemarkNode.cpp */,
+ 431476540CA838310090B3CE /* ossimPlanetKmlScreenOverlayNode.cpp */,
+ EED173970CA0174E00DF3588 /* ossimPlanetFadeText.cpp */,
+ 4315BDBF0C9717B400D36F21 /* ossimPlanetDtedElevationDatabase.cpp */,
+ 4315BDC10C9717B400D36F21 /* ossimPlanetCubeGrid.cpp */,
+ 4315BDC20C9717B400D36F21 /* ossimPlanetWmsImageLayer.cpp */,
+ 4315BDC30C9717B400D36F21 /* ossimPlanetUtility.cpp */,
+ 4315BDC40C9717B400D36F21 /* ossimPlanetThreadPool.cpp */,
+ 4315BDC50C9717B400D36F21 /* ossimPlanetThreadImp.cpp */,
+ 4315BDC60C9717B400D36F21 /* ossimPlanetThread.cpp */,
+ 4315BDC70C9717B400D36F21 /* ossimPlanetTextureLayerRegistry.cpp */,
+ 4315BDC80C9717B400D36F21 /* ossimPlanetTextureLayerGroup.cpp */,
+ 4315BDC90C9717B400D36F21 /* ossimPlanetTextureLayer.cpp */,
+ 4315BDCA0C9717B400D36F21 /* ossimPlanetStandardTextureLayerFactory.cpp */,
+ 4315BDCB0C9717B400D36F21 /* ossimPlanetSocketNetworkConnection.cpp */,
+ 4315BDCC0C9717B400D36F21 /* ossimPlanetShaderProgramSetup.cpp */,
+ 4315BDCD0C9717B400D36F21 /* ossimPlanetServerThread.cpp */,
+ 4315BDCE0C9717B400D36F21 /* ossimPlanetSceneView.cpp */,
+ 4315BDCF0C9717B400D36F21 /* ossimPlanetPlaneGrid.cpp */,
+ 4315BDD00C9717B400D36F21 /* ossimPlanetPagedLandLod.cpp */,
+ 4315BDD10C9717B400D36F21 /* ossimPlanetOssimImage.cpp */,
+ 4315BDD20C9717B400D36F21 /* ossimPlanetManipulator.cpp */,
+ 4315BDD30C9717B400D36F21 /* ossimPlanetNavigator.cpp */,
+ 4315BDD50C9717B400D36F21 /* ossimPlanetLookAt.cpp */,
+ 4315BDD60C9717B400D36F21 /* ossimPlanetLayer.cpp */,
+ 4315BDD70C9717B400D36F21 /* ossimPlanetLatLonHud.cpp */,
+ 4315BDD80C9717B400D36F21 /* ulError.cpp */,
+ 4315BDD90C9717B400D36F21 /* ulClock.cpp */,
+ 4315BDDA0C9717B400D36F21 /* sg_socket_udp.cpp */,
+ 4315BDDB0C9717B400D36F21 /* ossimPlanetYahooGeocoder.cpp */,
+ 4315BDDC0C9717B400D36F21 /* ossimPlanetWmsClient.cpp */,
+ 4315BDDD0C9717B400D36F21 /* ossimPlanetIoThread.cpp */,
+ 4315BDDE0C9717B400D36F21 /* ossimPlanetIoSocketServerChannel.cpp */,
+ 4315BDDF0C9717B400D36F21 /* ossimPlanetIoSocket.cpp */,
+ 4315BDE00C9717B400D36F21 /* ossimPlanetIoRoutableMessageHandler.cpp */,
+ 4315BDE10C9717B400D36F21 /* ossimPlanetInteractionController.cpp */,
+ 4315BDE20C9717B400D36F21 /* ossimPlanetImage.cpp */,
+ 4315BDE30C9717B400D36F21 /* ossimPlanetIdManager.cpp */,
+ 4315BDE40C9717B400D36F21 /* ossimPlanetClientThread.cpp */,
+ 4315BDE50C9717B400D36F21 /* ossimPlanetBoundingBox.cpp */,
+ 4315BDE60C9717B400D36F21 /* ossimPlanetBillboardIcon.cpp */,
+ 4315BDE70C9717B400D36F21 /* ossimPlanetKmlLayer.cpp */,
+ 4315BDE90C9717B400D36F21 /* ossimPlanetKml.cpp */,
+ 4315BDEA0C9717B400D36F21 /* ossimPlanetJpegImage.cpp */,
+ 4315BDEB0C9717B400D36F21 /* ossimPlanet.cpp */,
+ 4315BDEC0C9717B400D36F21 /* netSocket.cpp */,
+ 4315BDED0C9717B400D36F21 /* netMonitor.cpp */,
+ 4315BDEE0C9717B400D36F21 /* netMessage.cpp */,
+ 4315BDEF0C9717B400D36F21 /* netChat.cpp */,
+ 4315BDF00C9717B400D36F21 /* netChannel.cpp */,
+ 4315BDF10C9717B400D36F21 /* netBuffer.cpp */,
+ 4315BDF20C9717B400D36F21 /* mkUtils.cpp */,
+ 4315BDF30C9717B400D36F21 /* iochannel.cpp */,
+ 4315BDF40C9717B400D36F21 /* ossimPlanetGeocoder.cpp */,
+ 4315BDF60C9717B400D36F21 /* ossimPlanetActionRouter.cpp */,
+ 4315BDF70C9717B400D36F21 /* ossimPlanetActionReceiver.cpp */,
+ 4315BDF80C9717B400D36F21 /* ossimPlanetAction.cpp */,
+ 4315BDF90C9717B400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.cpp */,
+ 4315BDFA0C9717B400D36F21 /* ossimPlanetElevationGrid.cpp */,
+ 4315BDFB0C9717B400D36F21 /* ulLinkedList.cpp */,
+ 4315BDFC0C9717B400D36F21 /* ossimPlanetLandCache.cpp */,
+ 4315BDFD0C9717B400D36F21 /* ossimPlanetLand.cpp */,
+ 4315BDFE0C9717B400D36F21 /* ossimPlanetKmlLayerNode.cpp */,
+ 4315BDFF0C9717B400D36F21 /* sg_file.cpp */,
+ 4315BE000C9717B400D36F21 /* ossimPlanetTexture2D.cpp */,
+ 4315BE010C9717B400D36F21 /* ossimPlanetSrtmElevationDatabase.cpp */,
+ 4315BE020C9717B400D36F21 /* ossimPlanetId.cpp */,
+ 4315BE030C9717B400D36F21 /* ossimPlanetIconGeom.cpp */,
+ 4315BE050C9717B400D36F21 /* ossimPlanetGridUtility.cpp */,
+ 4315BE060C9717B400D36F21 /* ulRTTI.cpp */,
+ 4315BE070C9717B400D36F21 /* sg_socket.cpp */,
+ 4315BE080C9717B400D36F21 /* ossimPlanetOssimImageLayer.cpp */,
+ 4315BE090C9717B400D36F21 /* ul.cpp */,
+ 4315BE0A0C9717B400D36F21 /* ulList.cpp */,
+ 4315BE0B0C9717B400D36F21 /* ossimPlanetLandReaderWriter.cpp */,
+ 4315BE0C0C9717B400D36F21 /* ossimPlanetLandCullCallback.cpp */,
+ 4315BE0D0C9717B400D36F21 /* ossimPlanetElevationDatabaseGroup.cpp */,
+ 4315BE0E0C9717B400D36F21 /* ossimPlanetElevationDatabase.cpp */,
+ 43FDA2D90D77274F00945FA0 /* ossimPlanetDestinationCommandAction.cpp */,
+ 43AA128E0D77ADF90020DF13 /* ossimPlanetXmlAction.cpp */,
+ );
+ path = ossimPlanet;
+ sourceTree = "<group>";
+ };
+ 186EF4B50B1CE11D00F7886A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 186EF4F60B1CE11D00F7886A /* ossim.framework */,
+ 435310B71044384C004A4474 /* template-app */,
+ 435310B91044384C004A4474 /* ossim-adrg-dump */,
+ 435310BB1044384C004A4474 /* ossim-applanix2ogeom */,
+ 435310BD1044384C004A4474 /* ossim-band-merge */,
+ 435310BF1044384C004A4474 /* ossim-btoa */,
+ 435310C11044384C004A4474 /* template-app */,
+ 435310C31044384C004A4474 /* ossim-cmm */,
+ 435310C51044384C004A4474 /* ossim-computeSrtmStats */,
+ 435310C71044384C004A4474 /* ossim-correl */,
+ 435310C91044384C004A4474 /* ossim-create-cg */,
+ 435310CB1044384C004A4474 /* ossim-create-histo */,
+ 435310D31044384C004A4474 /* ossim-dms2deg */,
+ 435310D51044384C004A4474 /* ossim-dump-ocg */,
+ 435310D71044384C004A4474 /* ossim-ecg2ocg */,
+ 435310D91044384C004A4474 /* ossim-extract-vertices */,
+ 435310DB1044384C004A4474 /* ossim-foo */,
+ 435310DF1044384C004A4474 /* ossim-height */,
+ 435310E11044384C004A4474 /* ossim-icp */,
+ 435310E31044384C004A4474 /* ossim-igen */,
+ 435310E51044384C004A4474 /* ossim-img2md */,
+ 435310E71044384C004A4474 /* ossim-img2rr */,
+ 435310E91044384C004A4474 /* ossim-info */,
+ 435310EB1044384C004A4474 /* ossim-modopt */,
+ 435310ED1044384C004A4474 /* ossim-mosaic */,
+ 435310F31044384C004A4474 /* ossim-ogeom2ogeom */,
+ 435310F51044384C004A4474 /* ossim-orthoigen */,
+ 435310F71044384C004A4474 /* ossim-pixelflip */,
+ 435310F91044384C004A4474 /* ossim-prune */,
+ 435310FD1044384C004A4474 /* ossim-rejout */,
+ 435310FF1044384C004A4474 /* ossim-senint */,
+ 435311011044384C004A4474 /* ossim-space-imaging */,
+ 435311031044384C004A4474 /* ossim-swapbytes */,
+ 435311051044384C004A4474 /* ossim-tfw2ogeom */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 433A4CF5100CEDD2000B969C /* ossimplanettest */ = {
+ isa = PBXGroup;
+ children = (
+ 433A4CF6100CEDD2000B969C /* ossimplanettest.cpp */,
+ );
+ name = ossimplanettest;
+ path = ../../examples/ossimplanettest;
+ sourceTree = SOURCE_ROOT;
+ };
+ 437D9ACC0FC3FE810018F889 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 432933BA10FE531E00C66EB8 /* OpenThreads.framework */,
+ 43D7ECB210FE1F8500762FA7 /* gpstk.framework */,
+ 4306ABAE10FE11C000C7202A /* osgDB.framework */,
+ 4306ABAF10FE11C000C7202A /* osgText.framework */,
+ 4306ABB010FE11C000C7202A /* osgUtil.framework */,
+ 4306ABB110FE11C000C7202A /* osgViewer.framework */,
+ 4306ABAC10FE11AC00C7202A /* osgGA.framework */,
+ 4306ABAA10FE11A700C7202A /* osg.framework */,
+ 437D9DE60FC3FFA60018F889 /* OpenGL.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 43C6E2B40FEFB50E004B52F7 /* ossimplanetklv */ = {
+ isa = PBXGroup;
+ children = (
+ 43C6E2B60FEFB50E004B52F7 /* ossimplanetklv.cpp */,
+ );
+ name = ossimplanetklv;
+ path = ../../examples/ossimplanetklv;
+ sourceTree = SOURCE_ROOT;
+ };
+ 43C6E2B80FEFB531004B52F7 /* ossimplanetviewer */ = {
+ isa = PBXGroup;
+ children = (
+ 43C6E2C30FEFB531004B52F7 /* ossimplanetviewer.cpp */,
+ 43C6E2C50FEFB531004B52F7 /* readme.txt */,
+ );
+ name = ossimplanetviewer;
+ path = ../../examples/ossimplanetviewer;
+ sourceTree = SOURCE_ROOT;
+ };
+ 43D8A1060D818DFD00A60690 /* schema */ = {
+ isa = PBXGroup;
+ children = (
+ 43D8A1080D818E2200A60690 /* ossimPlanet.xsd */,
+ );
+ name = schema;
+ sourceTree = "<group>";
+ };
+ 43D8A10D0D818EC100A60690 /* Sample files */ = {
+ isa = PBXGroup;
+ children = (
+ 43D8A1120D818ED300A60690 /* binds.act */,
+ );
+ name = "Sample files";
+ sourceTree = "<group>";
+ };
+ EE69A34C0B2883FA00C91DD1 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ EE69A3500B2883FA00C91DD1 /* wms.framework */,
+ 437A55AD0E789BB8000D89D5 /* wmsurl */,
+ 437A55AF0E789BB8000D89D5 /* wmscapabilities.cpp */,
+ 437A55B10E789BB8000D89D5 /* wmsgetmap */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ EE9D25F30DD87952005A8951 /* apps */ = {
+ isa = PBXGroup;
+ children = (
+ 433A4CF5100CEDD2000B969C /* ossimplanettest */,
+ 43C6E2B40FEFB50E004B52F7 /* ossimplanetklv */,
+ 43C6E2B80FEFB531004B52F7 /* ossimplanetviewer */,
+ );
+ name = apps;
+ sourceTree = "<group>";
+ };
+ EEB5ECED0D0F2284000CF6B2 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ EEB5ECF10D0F2284000CF6B2 /* ossimPredator.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 430485FE0F3CB80800B9C1E2 /* ossimPlanetDatabasePager.h in Headers */,
+ EE26B26A0F39DD2000D4028C /* ossimPlanetElevationFactory.h in Headers */,
+ EE26B23A0F39CB8400D4028C /* ossimPlanetElevationRegistry.h in Headers */,
+ 435BD1FC0F09848100CEAEAD /* ossimPlanetViewer.h in Headers */,
+ EE2F90FD0EB5E188003D424A /* ossimPlanetMessage.h in Headers */,
+ 43CA034E0DD34451003EC1AB /* ossimPlanetArchive.h in Headers */,
+ 43CA034F0DD34451003EC1AB /* ossimPlanetArchiveMapping.h in Headers */,
+ 43A113DF0D520F3600DE3CF3 /* ossimPlanetNodeFactory.h in Headers */,
+ 43A113E00D520F3600DE3CF3 /* ossimPlanetNodeRegistry.h in Headers */,
+ 43A113E10D520F3600DE3CF3 /* ossimPlanetNodeFactoryBase.h in Headers */,
+ 43A113980D520D7100DE3CF3 /* ossimPlanetNode.h in Headers */,
+ 43C443DE0D4A2179004BDD99 /* ossimPlanetOperation.h in Headers */,
+ EEBDDA7A0D491078009DB3D5 /* ossimPlanetVideoLayerNode.h in Headers */,
+ EEBDD6CC0D46E214009DB3D5 /* ossimPlanetAnnotationLayerNode.h in Headers */,
+ EEBDD68E0D464823009DB3D5 /* ossimPlanetAnnotationLayer.h in Headers */,
+ 433E7EC20D32B9CF00BA05D0 /* ossimPlanetApi.h in Headers */,
+ 434EDC3C0D2BD04400EDC08A /* ossimPlanetLayerFactory.h in Headers */,
+ 434EDC1A0D2BCC8000EDC08A /* ossimPlanetLayerFactoryBase.h in Headers */,
+ 434EDC180D2BCA2600EDC08A /* ossimPlanetLayerRegistry.h in Headers */,
+ 43E957E00D2931C000D31E60 /* ossimPlanetRefBlock.h in Headers */,
+ EEB5EDDE0D101268000CF6B2 /* ossimPlanetPredatorVideoLayerNode.h in Headers */,
+ EEB5ECDA0D0F214E000CF6B2 /* ossimPlanetVideoLayer.h in Headers */,
+ 43669A930CD177A400F1832B /* ossimPlanetSousaLayer.h in Headers */,
+ 432FACB90CC4F2D6004D5C1D /* ossimPlanetCallback.h in Headers */,
+ 4314728F0CBE9F0F00EAADAB /* ossimPlanetVisitors.h in Headers */,
+ 430C8F690CBBD0CA002BAF12 /* ossimPlanetCompass.h in Headers */,
+ 432D60BC0CB548DE00F15133 /* ioapi.h in Headers */,
+ 432D60BD0CB548DE00F15133 /* unzip.h in Headers */,
+ 432D60BE0CB548DE00F15133 /* zip.h in Headers */,
+ 43C8A82E0CAACB4E00EE840F /* ossimPlanetKmlPlacemarkNode.h in Headers */,
+ 431476570CA838400090B3CE /* ossimPlanetKmlScreenOverlayNode.h in Headers */,
+ EED173960CA0174100DF3588 /* ossimPlanetFadeText.h in Headers */,
+ 4315BEC80C9717E400D36F21 /* ossimPlanetLandTreeNode.h in Headers */,
+ 4315BEC90C9717E400D36F21 /* ossimPlanetLandNormalType.h in Headers */,
+ 4315BECA0C9717E400D36F21 /* ossimPlanetKmlLayerNode.h in Headers */,
+ 4315BECB0C9717E400D36F21 /* netBuffer.h in Headers */,
+ 4315BECC0C9717E400D36F21 /* ossimPlanetLand.h in Headers */,
+ 4315BECD0C9717E400D36F21 /* ossimPlanetBillboardIcon.h in Headers */,
+ 4315BECF0C9717E400D36F21 /* ossimPlanetElevationDatabaseGroup.h in Headers */,
+ 4315BED00C9717E400D36F21 /* ossimPlanetIdolLayer.h in Headers */,
+ 4315BED20C9717E400D36F21 /* ossimPlanetIdManager.h in Headers */,
+ 4315BED30C9717E400D36F21 /* ossimPlanetLandReaderWriter.h in Headers */,
+ 4315BED40C9717E400D36F21 /* ossimPlanetUtility.h in Headers */,
+ 4315BED50C9717E400D36F21 /* ossimPlanetThreadPool.h in Headers */,
+ 4315BED60C9717E400D36F21 /* ossimPlanetPlaneGrid.h in Headers */,
+ 4315BED70C9717E400D36F21 /* ossimPlanetPagedRequestNode.h in Headers */,
+ 4315BED80C9717E400D36F21 /* ossimPlanetPagedLandLodRefreshType.h in Headers */,
+ 4315BED90C9717E400D36F21 /* ossimPlanetLandNode.h in Headers */,
+ 4315BEDA0C9717E400D36F21 /* ossimPlanetIoSocket.h in Headers */,
+ 4315BEDB0C9717E400D36F21 /* ossimPlanetInteractionController.h in Headers */,
+ 4315BEDC0C9717E400D36F21 /* ulLocal.h in Headers */,
+ 4315BEDD0C9717E400D36F21 /* ul.h in Headers */,
+ 4315BEDE0C9717E400D36F21 /* ossimPlanetInputDevice.h in Headers */,
+ 4315BEDF0C9717E400D36F21 /* ossimPlanetShaderProgramSetup.h in Headers */,
+ 4315BEE00C9717E400D36F21 /* ossimPlanetSetup.h in Headers */,
+ 4315BEE10C9717E400D36F21 /* ossimPlanetBoundingBox.h in Headers */,
+ 4315BEF80C9717E400D36F21 /* ossimPlanetOssimImageLayer.h in Headers */,
+ 4315BEE20C9717E400D36F21 /* ossimPlanetIoSocketServerChannel.h in Headers */,
+ 4315BEE30C9717E400D36F21 /* ossimPlanetPrimaryBody.h in Headers */,
+ 4315BEE40C9717E400D36F21 /* ossimPlanetSocketNetworkConnection.h in Headers */,
+ 4315BEE50C9717E400D36F21 /* iochannel.h in Headers */,
+ 4315BEE60C9717E400D36F21 /* ossimPlanetIconGeom.h in Headers */,
+ 4315BEE70C9717E400D36F21 /* ossimPlanetTextureLayer.h in Headers */,
+ 4315BEE80C9717E400D36F21 /* ossimPlanetTexture2D.h in Headers */,
+ 4315BEE90C9717E400D36F21 /* ossimPlanetAction.h in Headers */,
+ 4315BEEA0C9717E400D36F21 /* ossimPlanetServerMessageHandler.h in Headers */,
+ 4315BEEB0C9717E400D36F21 /* ossimPlanetSceneView.h in Headers */,
+ 4315BEEC0C9717E400D36F21 /* ossimPlanetManipulator.h in Headers */,
+ 4315BEED0C9717E400D36F21 /* ossimPlanetWmsImageLayer.h in Headers */,
+ 4315BEEE0C9717E400D36F21 /* ossimPlanetThread.h in Headers */,
+ 4315BEEF0C9717E400D36F21 /* ossimPlanetTextureLayerRegistry.h in Headers */,
+ 4315BEF00C9717E400D36F21 /* netChat.h in Headers */,
+ 4315BEF10C9717E400D36F21 /* ossimPlanetTextureLayerGroup.h in Headers */,
+ 4315BEF20C9717E400D36F21 /* ossimPlanetTextureLayerFactory.h in Headers */,
+ 4315BEF30C9717E400D36F21 /* ossimPlanetOssimImage.h in Headers */,
+ 4315BEF40C9717E400D36F21 /* ossimPlanetOrthoFlatLandNode.h in Headers */,
+ 4315BEF50C9717E400D36F21 /* ossimPlanetServerThread.h in Headers */,
+ 4315BEF60C9717E400D36F21 /* ossimPlanetIoThread.h in Headers */,
+ 4315BEF70C9717E400D36F21 /* ossimPlanet.h in Headers */,
+ 4315BEF90C9717E400D36F21 /* ossimPlanetThreadImp.h in Headers */,
+ 4315BEFB0C9717E400D36F21 /* ossimPlanetLandTextureRequest.h in Headers */,
+ 4315BEFC0C9717E400D36F21 /* ossimPlanetLandCullCallback.h in Headers */,
+ 4315BEFD0C9717E400D36F21 /* ossimPlanetConstants.h in Headers */,
+ 4315BEFE0C9717E400D36F21 /* ossimPlanetNetworkConnection.h in Headers */,
+ 4315BEFF0C9717E400D36F21 /* ossimPlanetKml.h in Headers */,
+ 4315BF010C9717E400D36F21 /* ossimPlanetExport.h in Headers */,
+ 4315BF020C9717E400D36F21 /* netMessage.h in Headers */,
+ 4315BF030C9717E400D36F21 /* ossimPlanetIo.h in Headers */,
+ 4315BF040C9717E400D36F21 /* ossimPlanetJpegImage.h in Headers */,
+ 4315BF050C9717E400D36F21 /* ossimPlanetLookAt.h in Headers */,
+ 4315BF080C9717E400D36F21 /* net.h in Headers */,
+ 4315BF090C9717E400D36F21 /* ulRTTI.h in Headers */,
+ 4315BF0A0C9717E400D36F21 /* netChannel.h in Headers */,
+ 4315BF0B0C9717E400D36F21 /* ossimPlanetElevationGrid.h in Headers */,
+ 4315BF0C0C9717E400D36F21 /* ossimPlanetIntersectUserData.h in Headers */,
+ 4315BF0D0C9717E400D36F21 /* ossimPlanetLabelGeom.h in Headers */,
+ 4315BF0E0C9717E400D36F21 /* ossimPlanetGeocoder.h in Headers */,
+ 4315BF0F0C9717E400D36F21 /* ossimPlanetLayer.h in Headers */,
+ 4315BF100C9717E400D36F21 /* netMonitor.h in Headers */,
+ 4315BF110C9717E400D36F21 /* ossimPlanetId.h in Headers */,
+ 4315BF130C9717E400D36F21 /* ossimPlanetActionRouter.h in Headers */,
+ 4315BF140C9717E400D36F21 /* ossimPlanetSrtmElevationDatabase.h in Headers */,
+ 4315BF150C9717E400D36F21 /* ossimPlanetStandardTextureLayerFactory.h in Headers */,
+ 4315BF160C9717E400D36F21 /* ossimPlanetActionReceiver.h in Headers */,
+ 4315BF170C9717E400D36F21 /* sg_file.h in Headers */,
+ 4315BF180C9717E400D36F21 /* ossimPlanetYahooGeocoder.h in Headers */,
+ 4315BF190C9717E400D36F21 /* ossimPlanetIoMessageHandler.h in Headers */,
+ 4315BF1A0C9717E400D36F21 /* ossimPlanetElevationDatabase.h in Headers */,
+ 4315BF1B0C9717E400D36F21 /* compiler.h in Headers */,
+ 4315BF1C0C9717E400D36F21 /* ossimPlanetLandCache.h in Headers */,
+ 4315BF1D0C9717E400D36F21 /* ossimPlanetExtents.h in Headers */,
+ 4315BF1E0C9717E400D36F21 /* ossimPlanetKmlReaderWriter.h in Headers */,
+ 4315BF1F0C9717E400D36F21 /* ossimPlanetDtedElevationDatabase.h in Headers */,
+ 4315BF200C9717E400D36F21 /* ossimPlanetNavigator.h in Headers */,
+ 4315BF210C9717E400D36F21 /* ossimPlanetImage.h in Headers */,
+ 4315BF220C9717E400D36F21 /* sg_socket_udp.h in Headers */,
+ 4315BF230C9717E400D36F21 /* sg_socket.h in Headers */,
+ 4315BF240C9717E400D36F21 /* ossimPlanetCubeGrid.h in Headers */,
+ 4315BF250C9717E400D36F21 /* ossimPlanetIdolBridge.h in Headers */,
+ 4315BF270C9717E400D36F21 /* mkUtils.h in Headers */,
+ 4315BF280C9717E400D36F21 /* ossimPlanetLatLonHud.h in Headers */,
+ 4315BF290C9717E400D36F21 /* ossimPlanetClientThread.h in Headers */,
+ 4315BF2A0C9717E400D36F21 /* ossimPlanetIoRoutableMessageHandler.h in Headers */,
+ 4315BF2B0C9717E400D36F21 /* ossimPlanetPagedLandLod.h in Headers */,
+ 4315BF2C0C9717E400D36F21 /* ossimPlanetWmsClient.h in Headers */,
+ 4315BF2D0C9717E400D36F21 /* netSocket.h in Headers */,
+ 4315BF2E0C9717E400D36F21 /* ossimPlanetKmlLayer.h in Headers */,
+ 4315BF2F0C9717E400D36F21 /* ossimPlanetGridUtility.h in Headers */,
+ 4315BF300C9717E400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.h in Headers */,
+ 43FDA2D70D770D0700945FA0 /* ossimPlanetDestinationCommandAction.h in Headers */,
+ 43FDA3D30D77495200945FA0 /* ossimPlanetXmlAction.h in Headers */,
+ EE5403670F5D7041001139DD /* ossimPlanetTerrain.h in Headers */,
+ EE54036A0F5D74F5001139DD /* ossimPlanetTerrainTile.h in Headers */,
+ EE5403EE0F5D8C50001139DD /* ossimPlanetGrid.h in Headers */,
+ EE5403F10F5D8DDE001139DD /* ossimPlanetTerrainTileId.h in Headers */,
+ EE5404570F5E21DD001139DD /* ossimPlanetTerrainTechnique.h in Headers */,
+ EE54045A0F5E24D2001139DD /* ossimPlanetTerrainGeometryTechnique.h in Headers */,
+ EE5409A30F61516D001139DD /* ossimPlanetPointModel.h in Headers */,
+ EE540A8F0F61A503001139DD /* ossimPlanetGeoRefModel.h in Headers */,
+ EE9B0A4D0F6463A500394285 /* ossimPlanetLsrSpaceTransform.h in Headers */,
+ 43D65A310F6839F1006C6786 /* ossimPlanetTerrainLayer.h in Headers */,
+ 43244C830F742D70002F5FA3 /* ossimPlanetReentrantMutex.h in Headers */,
+ 43BC2F8F0F8D13C600838B40 /* ossimPlanetTileRequest.h in Headers */,
+ 4351096E0FCC130A0065BA0E /* ossimPlanetViewMatrixBuilder.h in Headers */,
+ 43463BC00FCF16DD0027D845 /* ossimPlanetAnimationPath.h in Headers */,
+ 4345891E0FD3F96C00046CB5 /* ossimPlanetAnimatedPointModel.h in Headers */,
+ 43AB5FAF0FF99226004874C2 /* ossimPlanetEphemeris.h in Headers */,
+ 43FF0C201021065500CEA135 /* ossimPlanetCloudLayer.h in Headers */,
+ 4377D4281029BB5800B6652D /* ossimPlanetCache.h in Headers */,
+ 4377D6FB102C50AD00B6652D /* ossimPlanetKmlNetworkLinkNode.h in Headers */,
+ 43D9C7E510A4BC0F00BA9119 /* ossimPlanetCacheTextureLayer.h in Headers */,
+ 434E72BC10DAAD15005EBB18 /* ossimPlanetOssimElevationDatabase.h in Headers */,
+ 430D8E911100DA3F00EB0F96 /* ossimPlanetDepthPartitionNode.h in Headers */,
+ 430D8E941100DA5200EB0F96 /* ossimPlanetDistanceAccumulator.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 433A4CC4100CED8D000B969C /* ossimplanettest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 433A4CD2100CED8D000B969C /* Build configuration list for PBXNativeTarget "ossimplanettest" */;
+ buildPhases = (
+ 433A4CC7100CED8D000B969C /* Sources */,
+ 433A4CC9100CED8D000B969C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 433A4CC5100CED8D000B969C /* PBXTargetDependency */,
+ );
+ name = ossimplanettest;
+ productName = ossimplanetviewer;
+ productReference = 433A4CD8100CED8D000B969C /* ossimplanettest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 43C6E2900FEFB4D8004B52F7 /* ossimplanetklv */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 43C6E2B00FEFB4F1004B52F7 /* Build configuration list for PBXNativeTarget "ossimplanetklv" */;
+ buildPhases = (
+ 43C6E28E0FEFB4D8004B52F7 /* Sources */,
+ 43C6E28F0FEFB4D8004B52F7 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ossimplanetklv;
+ productName = ossimplanetklv;
+ productReference = 43C6E2910FEFB4D8004B52F7 /* ossimplanetklv */;
+ productType = "com.apple.product-type.tool";
+ };
+ 43C6E29B0FEFB4E9004B52F7 /* ossimplanetviewer */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 43C6E2B10FEFB4F1004B52F7 /* Build configuration list for PBXNativeTarget "ossimplanetviewer" */;
+ buildPhases = (
+ 43C6E2990FEFB4E9004B52F7 /* Sources */,
+ 43C6E29A0FEFB4E9004B52F7 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 43AB5F2B0FF94015004874C2 /* PBXTargetDependency */,
+ );
+ name = ossimplanetviewer;
+ productName = ossimplanetviewer;
+ productReference = 43C6E29C0FEFB4E9004B52F7 /* ossimplanetviewer */;
+ productType = "com.apple.product-type.tool";
+ };
+ 8D07F2BC0486CC7A007CD1D0 /* ossimPlanet */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "ossimPlanet" */;
+ buildPhases = (
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */,
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */,
+ 8D07F2C10486CC7A007CD1D0 /* Sources */,
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */,
+ 8D07F2C50486CC7A007CD1D0 /* Rez */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ EEB5EE5E0D103A68000CF6B2 /* PBXTargetDependency */,
+ EEB5EE5C0D103A57000CF6B2 /* PBXTargetDependency */,
+ EEB5EE5A0D103A4A000CF6B2 /* PBXTargetDependency */,
+ );
+ name = ossimPlanet;
+ productInstallPath = "$(HOME)/Library/Frameworks";
+ productName = ossimPlanet;
+ productReference = 8D07F2C80486CC7A007CD1D0 /* ossimPlanet.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "ossimPlanet" */;
+ compatibilityVersion = "Xcode 2.4";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 0867D691FE84028FC02AAC07 /* ossimPlanet */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = EE69A34C0B2883FA00C91DD1 /* Products */;
+ ProjectRef = EE69A34B0B2883FA00C91DD1 /* libwms.xcodeproj */;
+ },
+ {
+ ProductGroup = 186EF4B50B1CE11D00F7886A /* Products */;
+ ProjectRef = 186EF4B40B1CE11D00F7886A /* ossim.xcodeproj */;
+ },
+ {
+ ProductGroup = EEB5ECED0D0F2284000CF6B2 /* Products */;
+ ProjectRef = EEB5ECEC0D0F2284000CF6B2 /* ossimPredator.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ EE9D26590DD888FB005A8951 /* All */,
+ 8D07F2BC0486CC7A007CD1D0 /* ossimPlanet */,
+ 43C6E2900FEFB4D8004B52F7 /* ossimplanetklv */,
+ 43C6E29B0FEFB4E9004B52F7 /* ossimplanetviewer */,
+ 433A4CC4100CED8D000B969C /* ossimplanettest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 186EF4F60B1CE11D00F7886A /* ossim.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ossim.framework;
+ remoteRef = 186EF4F50B1CE11D00F7886A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310B71044384C004A4474 /* template-app */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "template-app";
+ remoteRef = 435310B61044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310B91044384C004A4474 /* ossim-adrg-dump */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-adrg-dump";
+ remoteRef = 435310B81044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310BB1044384C004A4474 /* ossim-applanix2ogeom */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-applanix2ogeom";
+ remoteRef = 435310BA1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310BD1044384C004A4474 /* ossim-band-merge */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-band-merge";
+ remoteRef = 435310BC1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310BF1044384C004A4474 /* ossim-btoa */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-btoa";
+ remoteRef = 435310BE1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310C11044384C004A4474 /* template-app */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "template-app";
+ remoteRef = 435310C01044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310C31044384C004A4474 /* ossim-cmm */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-cmm";
+ remoteRef = 435310C21044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310C51044384C004A4474 /* ossim-computeSrtmStats */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-computeSrtmStats";
+ remoteRef = 435310C41044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310C71044384C004A4474 /* ossim-correl */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-correl";
+ remoteRef = 435310C61044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310C91044384C004A4474 /* ossim-create-cg */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-create-cg";
+ remoteRef = 435310C81044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310CB1044384C004A4474 /* ossim-create-histo */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-create-histo";
+ remoteRef = 435310CA1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310D31044384C004A4474 /* ossim-dms2deg */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-dms2deg";
+ remoteRef = 435310D21044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310D51044384C004A4474 /* ossim-dump-ocg */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-dump-ocg";
+ remoteRef = 435310D41044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310D71044384C004A4474 /* ossim-ecg2ocg */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-ecg2ocg";
+ remoteRef = 435310D61044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310D91044384C004A4474 /* ossim-extract-vertices */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-extract-vertices";
+ remoteRef = 435310D81044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310DB1044384C004A4474 /* ossim-foo */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-foo";
+ remoteRef = 435310DA1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310DF1044384C004A4474 /* ossim-height */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-height";
+ remoteRef = 435310DE1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310E11044384C004A4474 /* ossim-icp */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-icp";
+ remoteRef = 435310E01044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310E31044384C004A4474 /* ossim-igen */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-igen";
+ remoteRef = 435310E21044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310E51044384C004A4474 /* ossim-img2md */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-img2md";
+ remoteRef = 435310E41044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310E71044384C004A4474 /* ossim-img2rr */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-img2rr";
+ remoteRef = 435310E61044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310E91044384C004A4474 /* ossim-info */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-info";
+ remoteRef = 435310E81044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310EB1044384C004A4474 /* ossim-modopt */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-modopt";
+ remoteRef = 435310EA1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310ED1044384C004A4474 /* ossim-mosaic */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-mosaic";
+ remoteRef = 435310EC1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310F31044384C004A4474 /* ossim-ogeom2ogeom */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-ogeom2ogeom";
+ remoteRef = 435310F21044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310F51044384C004A4474 /* ossim-orthoigen */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-orthoigen";
+ remoteRef = 435310F41044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310F71044384C004A4474 /* ossim-pixelflip */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-pixelflip";
+ remoteRef = 435310F61044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310F91044384C004A4474 /* ossim-prune */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-prune";
+ remoteRef = 435310F81044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310FD1044384C004A4474 /* ossim-rejout */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-rejout";
+ remoteRef = 435310FC1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435310FF1044384C004A4474 /* ossim-senint */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-senint";
+ remoteRef = 435310FE1044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435311011044384C004A4474 /* ossim-space-imaging */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-space-imaging";
+ remoteRef = 435311001044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435311031044384C004A4474 /* ossim-swapbytes */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-swapbytes";
+ remoteRef = 435311021044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 435311051044384C004A4474 /* ossim-tfw2ogeom */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = "ossim-tfw2ogeom";
+ remoteRef = 435311041044384C004A4474 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 437A55AD0E789BB8000D89D5 /* wmsurl */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = wmsurl;
+ remoteRef = 437A55AC0E789BB8000D89D5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 437A55AF0E789BB8000D89D5 /* wmscapabilities.cpp */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = wmscapabilities.cpp;
+ remoteRef = 437A55AE0E789BB8000D89D5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 437A55B10E789BB8000D89D5 /* wmsgetmap */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = wmsgetmap;
+ remoteRef = 437A55B00E789BB8000D89D5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ EE69A3500B2883FA00C91DD1 /* wms.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = wms.framework;
+ remoteRef = EE69A34F0B2883FA00C91DD1 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ EEB5ECF10D0F2284000CF6B2 /* ossimPredator.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ossimPredator.framework;
+ remoteRef = EEB5ECF00D0F2284000CF6B2 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */,
+ 43D8A1090D818E2200A60690 /* ossimPlanet.xsd in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+ 8D07F2C50486CC7A007CD1D0 /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 433A4CC7100CED8D000B969C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 433A4CF7100CEDD2000B969C /* ossimplanettest.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 43C6E28E0FEFB4D8004B52F7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 43C6E2B70FEFB50E004B52F7 /* ossimplanetklv.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 43C6E2990FEFB4E9004B52F7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 43C6E2C90FEFB531004B52F7 /* ossimplanetviewer.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4315BE0F0C9717B400D36F21 /* ossimPlanetDtedElevationDatabase.cpp in Sources */,
+ 4315BE110C9717B400D36F21 /* ossimPlanetCubeGrid.cpp in Sources */,
+ 4315BE120C9717B400D36F21 /* ossimPlanetWmsImageLayer.cpp in Sources */,
+ 4315BE130C9717B400D36F21 /* ossimPlanetUtility.cpp in Sources */,
+ 4315BE140C9717B400D36F21 /* ossimPlanetThreadPool.cpp in Sources */,
+ 4315BE150C9717B400D36F21 /* ossimPlanetThreadImp.cpp in Sources */,
+ 4315BE160C9717B400D36F21 /* ossimPlanetThread.cpp in Sources */,
+ 4315BE170C9717B400D36F21 /* ossimPlanetTextureLayerRegistry.cpp in Sources */,
+ 4315BE180C9717B400D36F21 /* ossimPlanetTextureLayerGroup.cpp in Sources */,
+ 4315BE190C9717B400D36F21 /* ossimPlanetTextureLayer.cpp in Sources */,
+ 4315BE1A0C9717B400D36F21 /* ossimPlanetStandardTextureLayerFactory.cpp in Sources */,
+ 4315BE1B0C9717B400D36F21 /* ossimPlanetSocketNetworkConnection.cpp in Sources */,
+ 4315BE1C0C9717B400D36F21 /* ossimPlanetShaderProgramSetup.cpp in Sources */,
+ 4315BE1D0C9717B400D36F21 /* ossimPlanetServerThread.cpp in Sources */,
+ 4315BE1E0C9717B400D36F21 /* ossimPlanetSceneView.cpp in Sources */,
+ 4315BE1F0C9717B400D36F21 /* ossimPlanetPlaneGrid.cpp in Sources */,
+ 4315BE200C9717B400D36F21 /* ossimPlanetPagedLandLod.cpp in Sources */,
+ 4315BE210C9717B400D36F21 /* ossimPlanetOssimImage.cpp in Sources */,
+ 4315BE220C9717B400D36F21 /* ossimPlanetManipulator.cpp in Sources */,
+ 4315BE230C9717B400D36F21 /* ossimPlanetNavigator.cpp in Sources */,
+ 4315BE250C9717B400D36F21 /* ossimPlanetLookAt.cpp in Sources */,
+ 4315BE260C9717B400D36F21 /* ossimPlanetLayer.cpp in Sources */,
+ 4315BE270C9717B400D36F21 /* ossimPlanetLatLonHud.cpp in Sources */,
+ 4315BE280C9717B400D36F21 /* ulError.cpp in Sources */,
+ 4315BE290C9717B400D36F21 /* ulClock.cpp in Sources */,
+ 4315BE2A0C9717B400D36F21 /* sg_socket_udp.cpp in Sources */,
+ 4315BE2B0C9717B400D36F21 /* ossimPlanetYahooGeocoder.cpp in Sources */,
+ 4315BE2C0C9717B400D36F21 /* ossimPlanetWmsClient.cpp in Sources */,
+ 4315BE2D0C9717B400D36F21 /* ossimPlanetIoThread.cpp in Sources */,
+ 4315BE2E0C9717B400D36F21 /* ossimPlanetIoSocketServerChannel.cpp in Sources */,
+ 4315BE2F0C9717B400D36F21 /* ossimPlanetIoSocket.cpp in Sources */,
+ 4315BE300C9717B400D36F21 /* ossimPlanetIoRoutableMessageHandler.cpp in Sources */,
+ 4315BE310C9717B400D36F21 /* ossimPlanetInteractionController.cpp in Sources */,
+ 4315BE320C9717B400D36F21 /* ossimPlanetImage.cpp in Sources */,
+ 4315BE330C9717B400D36F21 /* ossimPlanetIdManager.cpp in Sources */,
+ 4315BE340C9717B400D36F21 /* ossimPlanetClientThread.cpp in Sources */,
+ 4315BE350C9717B400D36F21 /* ossimPlanetBoundingBox.cpp in Sources */,
+ 4315BE360C9717B400D36F21 /* ossimPlanetBillboardIcon.cpp in Sources */,
+ 4315BE370C9717B400D36F21 /* ossimPlanetKmlLayer.cpp in Sources */,
+ 4315BE390C9717B400D36F21 /* ossimPlanetKml.cpp in Sources */,
+ 4315BE3A0C9717B400D36F21 /* ossimPlanetJpegImage.cpp in Sources */,
+ 4315BE3B0C9717B400D36F21 /* ossimPlanet.cpp in Sources */,
+ 4315BE3C0C9717B400D36F21 /* netSocket.cpp in Sources */,
+ 4315BE3D0C9717B400D36F21 /* netMonitor.cpp in Sources */,
+ 4315BE3E0C9717B400D36F21 /* netMessage.cpp in Sources */,
+ 4315BE3F0C9717B400D36F21 /* netChat.cpp in Sources */,
+ 4315BE400C9717B400D36F21 /* netChannel.cpp in Sources */,
+ 4315BE410C9717B400D36F21 /* netBuffer.cpp in Sources */,
+ 4315BE420C9717B400D36F21 /* mkUtils.cpp in Sources */,
+ 4315BE430C9717B400D36F21 /* iochannel.cpp in Sources */,
+ 4315BE440C9717B400D36F21 /* ossimPlanetGeocoder.cpp in Sources */,
+ 4315BE460C9717B400D36F21 /* ossimPlanetActionRouter.cpp in Sources */,
+ 4315BE470C9717B400D36F21 /* ossimPlanetActionReceiver.cpp in Sources */,
+ 4315BE480C9717B400D36F21 /* ossimPlanetAction.cpp in Sources */,
+ 4315BE490C9717B400D36F21 /* ossimPlanetGeneralRasterElevationDatabase.cpp in Sources */,
+ 4315BE4A0C9717B400D36F21 /* ossimPlanetElevationGrid.cpp in Sources */,
+ 4315BE4B0C9717B400D36F21 /* ulLinkedList.cpp in Sources */,
+ 4315BE4C0C9717B400D36F21 /* ossimPlanetLandCache.cpp in Sources */,
+ 4315BE4D0C9717B400D36F21 /* ossimPlanetLand.cpp in Sources */,
+ 4315BE4E0C9717B400D36F21 /* ossimPlanetKmlLayerNode.cpp in Sources */,
+ 4315BE4F0C9717B400D36F21 /* sg_file.cpp in Sources */,
+ 4315BE500C9717B400D36F21 /* ossimPlanetTexture2D.cpp in Sources */,
+ 4315BE510C9717B400D36F21 /* ossimPlanetSrtmElevationDatabase.cpp in Sources */,
+ 4315BE520C9717B400D36F21 /* ossimPlanetId.cpp in Sources */,
+ 4315BE530C9717B400D36F21 /* ossimPlanetIconGeom.cpp in Sources */,
+ 4315BE550C9717B400D36F21 /* ossimPlanetGridUtility.cpp in Sources */,
+ 4315BE560C9717B400D36F21 /* ulRTTI.cpp in Sources */,
+ 4315BE570C9717B400D36F21 /* sg_socket.cpp in Sources */,
+ 4315BE580C9717B400D36F21 /* ossimPlanetOssimImageLayer.cpp in Sources */,
+ 4315BE590C9717B400D36F21 /* ul.cpp in Sources */,
+ 4315BE5A0C9717B400D36F21 /* ulList.cpp in Sources */,
+ 4315BE5B0C9717B400D36F21 /* ossimPlanetLandReaderWriter.cpp in Sources */,
+ 4315BE5C0C9717B400D36F21 /* ossimPlanetLandCullCallback.cpp in Sources */,
+ 4315BE5D0C9717B400D36F21 /* ossimPlanetElevationDatabaseGroup.cpp in Sources */,
+ 4315BE5E0C9717B400D36F21 /* ossimPlanetElevationDatabase.cpp in Sources */,
+ EED173980CA0174E00DF3588 /* ossimPlanetFadeText.cpp in Sources */,
+ 431476550CA838310090B3CE /* ossimPlanetKmlScreenOverlayNode.cpp in Sources */,
+ 43C8A8320CAACB6500EE840F /* ossimPlanetKmlPlacemarkNode.cpp in Sources */,
+ 432D60B60CB548C800F15133 /* ioapi.c in Sources */,
+ 432D60B70CB548C800F15133 /* unzip.c in Sources */,
+ 432D60B80CB548C800F15133 /* zip.c in Sources */,
+ 430C8F670CBBD0B9002BAF12 /* ossimPlanetCompass.cpp in Sources */,
+ 43669A950CD177CD00F1832B /* ossimPlanetSousaLayer.cpp in Sources */,
+ EEB5ECE50D0F220C000CF6B2 /* ossimPlanetVideoLayer.cpp in Sources */,
+ EEB5EDDC0D101235000CF6B2 /* ossimPlanetPredatorVideoLayerNode.cpp in Sources */,
+ 434EDC400D2BD20500EDC08A /* ossimPlanetLayerRegistry.cpp in Sources */,
+ 434EDC7C0D2BD8D200EDC08A /* ossimPlanetLayerFactory.cpp in Sources */,
+ 433E7EC80D32B9EC00BA05D0 /* ossimPlanetApi.cpp in Sources */,
+ EEBDD6920D465A0B009DB3D5 /* ossimPlanetAnnotationLayer.cpp in Sources */,
+ EEBDD6CF0D46E3AC009DB3D5 /* ossimPlanetAnnotationLayerNode.cpp in Sources */,
+ 43C443E30D4A2C6D004BDD99 /* ossimPlanetOperation.cpp in Sources */,
+ 43A52F150D4FA87100DB4777 /* ossimPlanetVisitors.cpp in Sources */,
+ 43A113950D520D5D00DE3CF3 /* ossimPlanetNode.cpp in Sources */,
+ 43A113E70D520F8900DE3CF3 /* ossimPlanetNodeFactory.cpp in Sources */,
+ 43A113E80D520F8900DE3CF3 /* ossimPlanetNodeRegistry.cpp in Sources */,
+ 43FDA2DA0D77274F00945FA0 /* ossimPlanetDestinationCommandAction.cpp in Sources */,
+ 43AA128F0D77ADF90020DF13 /* ossimPlanetXmlAction.cpp in Sources */,
+ 43CA03520DD34464003EC1AB /* ossimPlanetArchiveMapping.cpp in Sources */,
+ 43CA03530DD34464003EC1AB /* ossimPlanetArchive.cpp in Sources */,
+ EE0517BC0EE81BB6009EC91D /* ossimPlanetViewer.cpp in Sources */,
+ EE26B23D0F39CC0D00D4028C /* ossimPlanetElevationRegistry.cpp in Sources */,
+ EE26B2680F39DD1100D4028C /* ossimPlanetElevationFactory.cpp in Sources */,
+ EE5403650F5D7030001139DD /* ossimPlanetTerrain.cpp in Sources */,
+ EE5403790F5D7522001139DD /* ossimPlanetTerrainTile.cpp in Sources */,
+ EE5403EB0F5D8C42001139DD /* ossimPlanetGrid.cpp in Sources */,
+ EE5404550F5E21CF001139DD /* ossimPlanetTerrainTechnique.cpp in Sources */,
+ EE5404660F5E24EC001139DD /* ossimPlanetTerrainGeometryTechnique.cpp in Sources */,
+ EE5409A10F615143001139DD /* ossimPlanetPointModel.cpp in Sources */,
+ EE9B0A700F6463C400394285 /* ossimPlanetLsrSpaceTransform.cpp in Sources */,
+ 43D65A530F683B15006C6786 /* ossimPlanetTerrainLayer.cpp in Sources */,
+ 43BC2F8D0F8D13A600838B40 /* ossimPlanetTileRequest.cpp in Sources */,
+ 435109740FCC134C0065BA0E /* ossimPlanetViewMatrixBuilder.cpp in Sources */,
+ 43463BD70FCF78850027D845 /* ossimPlanetAnimationPath.cpp in Sources */,
+ 4345891C0FD3F95900046CB5 /* ossimPlanetAnimatedPointModel.cpp in Sources */,
+ 43AB5FB30FF99240004874C2 /* ossimPlanetEphemeris.cpp in Sources */,
+ 43FF0C261021068E00CEA135 /* ossimPlanetCloudLayer.cpp in Sources */,
+ 4377D42A1029BB7000B6652D /* ossimPlanetCache.cpp in Sources */,
+ 4377D6F8102C509900B6652D /* ossimPlanetKmlNetworkLinkNode.cpp in Sources */,
+ 43D9C7E010A4BBB900BA9119 /* ossimPlanetCacheTextureLayer.cpp in Sources */,
+ 434E72B910DAACEE005EBB18 /* ossimPlanetOssimElevationDatabase.cpp in Sources */,
+ 430D8E991100DB1F00EB0F96 /* ossimPlanetDepthPartitionNode.cpp in Sources */,
+ 430D8E9A1100DB1F00EB0F96 /* ossimPlanetDistanceAccumulator.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 433A4CC5100CED8D000B969C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D07F2BC0486CC7A007CD1D0 /* ossimPlanet */;
+ targetProxy = 433A4CC6100CED8D000B969C /* PBXContainerItemProxy */;
+ };
+ 43AB5F2B0FF94015004874C2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D07F2BC0486CC7A007CD1D0 /* ossimPlanet */;
+ targetProxy = 43AB5F2A0FF94015004874C2 /* PBXContainerItemProxy */;
+ };
+ 43DFCC080FF0F4E000FB2061 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 43C6E2900FEFB4D8004B52F7 /* ossimplanetklv */;
+ targetProxy = 43DFCC070FF0F4E000FB2061 /* PBXContainerItemProxy */;
+ };
+ 43DFCC0A0FF0F4E000FB2061 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 43C6E29B0FEFB4E9004B52F7 /* ossimplanetviewer */;
+ targetProxy = 43DFCC090FF0F4E000FB2061 /* PBXContainerItemProxy */;
+ };
+ EE9D26610DD8891C005A8951 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D07F2BC0486CC7A007CD1D0 /* ossimPlanet */;
+ targetProxy = EE9D26600DD8891C005A8951 /* PBXContainerItemProxy */;
+ };
+ EEB5EE5A0D103A4A000CF6B2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = ossimPredator;
+ targetProxy = EEB5EE590D103A4A000CF6B2 /* PBXContainerItemProxy */;
+ };
+ EEB5EE5C0D103A57000CF6B2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = ossim;
+ targetProxy = EEB5EE5B0D103A57000CF6B2 /* PBXContainerItemProxy */;
+ };
+ EEB5EE5E0D103A68000CF6B2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = wms;
+ targetProxy = EEB5EE5D0D103A68000CF6B2 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C1667FE841158C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 18A9BCBE0CDA158B00F4581A /* DebugNativeLeopard */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH)";
+ GCC_MODEL_TUNING = "";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(DEV_HOME_PATH)/ossim/include",
+ "$(DEV_HOME_PATH)/libwms/include",
+ "$(DEV_HOME_PATH)/ossimPlanet/include",
+ "$(UNIV_HEADER_DEP)",
+ );
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = (
+ "-DOSSIMPLANET_ENABLE_PREDATOR",
+ "-DOSSIMPLANET_ENABLE_EPHEMERIS",
+ "-g",
+ );
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+ };
+ name = DebugNativeLeopard;
+ };
+ 18A9BCBF0CDA158B00F4581A /* DebugNativeLeopard */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(inherited)";
+ COPY_PHASE_STRIP = NO;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = "";
+ GCC_OPTIMIZATION_LEVEL = s;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "";
+ GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_1 = "EXTRA_INFO_STRING_FOR_MENU=\\\"Version\\";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "$(inherited)";
+ OTHER_CPLUSPLUSFLAGS = "$(inherited)";
+ OTHER_LDFLAGS = /usr/lib/libz.dylib;
+ PRODUCT_NAME = ossimPlanet;
+ REZ_SEARCH_PATHS = (
+ "$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+ "$(REZ_SEARCH_PATHS)/**",
+ );
+ USER_HEADER_SEARCH_PATHS = "$(OSSIM_HOME_PATH)/include $(DEV_HOME_PATH)/libwms/include $(DEV_HOME_PATH)/ossimPlanet/include $(UNIV_HEADER_DEP) /usr/X11R6/include/freetype2 /usr/X11R6/include";
+ WARNING_CFLAGS = "-Wall";
+ WRAPPER_EXTENSION = framework;
+ ZERO_LINK = YES;
+ };
+ name = DebugNativeLeopard;
+ };
+ 18B28C4F0CD57AB3008F45B2 /* ReleaseLeopard */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ i386,
+ ppc,
+ );
+ GCC_MODEL_TUNING = "";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(DEV_HOME_PATH)/ossim/include",
+ "$(DEV_HOME_PATH)/libwms/include",
+ "$(DEV_HOME_PATH)/ossimPlanet/include",
+ "$(UNIV_HEADER_DEP)",
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = (
+ "-DOSSIMPLANET_ENABLE_PREDATOR",
+ "-DOSSIMPLANET_ENABLE_EPHEMERIS",
+ "-g",
+ );
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+ };
+ name = ReleaseLeopard;
+ };
+ 18B28C500CD57AB3008F45B2 /* ReleaseLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(inherited)";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = "";
+ GCC_OPTIMIZATION_LEVEL = s;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "$(inherited)";
+ OTHER_CPLUSPLUSFLAGS = "$(inherited)";
+ OTHER_LDFLAGS = /usr/lib/libz.dylib;
+ PRODUCT_NAME = ossimPlanet;
+ REZ_SEARCH_PATHS = (
+ "$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+ "$(REZ_SEARCH_PATHS)/**",
+ );
+ USER_HEADER_SEARCH_PATHS = "$(DEV_HOME_PATH)/ossim/include $(DEV_HOME_PATH)/libwms/include $(DEV_HOME_PATH)/ossimPlanet/include $(UNIV_HEADER_DEP)";
+ WARNING_CFLAGS = "-Wall";
+ WRAPPER_EXTENSION = framework;
+ };
+ name = ReleaseLeopard;
+ };
+ 18E4E5560BE7802B00C8442B /* DebugNative */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(inherited)";
+ COPY_PHASE_STRIP = NO;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = "";
+ GCC_OPTIMIZATION_LEVEL = s;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "";
+ GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_1 = "EXTRA_INFO_STRING_FOR_MENU=\\\"Version\\";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "$(inherited)";
+ OTHER_CPLUSPLUSFLAGS = "$(inherited)";
+ OTHER_LDFLAGS = /usr/lib/libz.dylib;
+ PRODUCT_NAME = ossimPlanet;
+ REZ_SEARCH_PATHS = (
+ "$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+ "$(REZ_SEARCH_PATHS)/**",
+ );
+ USER_HEADER_SEARCH_PATHS = "$(OSSIM_HOME_PATH)/include $(DEV_HOME_PATH)/libwms/include $(DEV_HOME_PATH)/ossimPlanet/include $(UNIV_HEADER_DEP) /usr/X11R6/include/freetype2 /usr/X11R6/include";
+ WARNING_CFLAGS = "-Wall";
+ WRAPPER_EXTENSION = framework;
+ ZERO_LINK = YES;
+ };
+ name = DebugNative;
+ };
+ 18E4E5570BE7802B00C8442B /* DebugNative */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH)";
+ GCC_MODEL_TUNING = "";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(DEV_HOME_PATH)/ossim/include",
+ "$(DEV_HOME_PATH)/libwms/include",
+ "$(DEV_HOME_PATH)/ossimPlanet/include",
+ "$(UNIV_HEADER_DEP)",
+ );
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = (
+ "-DOSSIMPLANET_ENABLE_PREDATOR",
+ "-DOSSIMPLANET_ENABLE_EPHEMERIS",
+ "-g",
+ );
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ };
+ name = DebugNative;
+ };
+ 433A4CD3100CED8D000B969C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanettest;
+ };
+ name = Debug;
+ };
+ 433A4CD4100CED8D000B969C /* DebugNative */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanettest;
+ };
+ name = DebugNative;
+ };
+ 433A4CD5100CED8D000B969C /* DebugNativeLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanettest;
+ };
+ name = DebugNativeLeopard;
+ };
+ 433A4CD6100CED8D000B969C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanettest;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 433A4CD7100CED8D000B969C /* ReleaseLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanettest;
+ };
+ name = ReleaseLeopard;
+ };
+ 43C6E2930FEFB4DA004B52F7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetklv;
+ };
+ name = Debug;
+ };
+ 43C6E2940FEFB4DA004B52F7 /* DebugNative */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetklv;
+ };
+ name = DebugNative;
+ };
+ 43C6E2950FEFB4DA004B52F7 /* DebugNativeLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetklv;
+ };
+ name = DebugNativeLeopard;
+ };
+ 43C6E2960FEFB4DA004B52F7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetklv;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 43C6E2970FEFB4DA004B52F7 /* ReleaseLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetklv;
+ };
+ name = ReleaseLeopard;
+ };
+ 43C6E29E0FEFB4EA004B52F7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetviewer;
+ };
+ name = Debug;
+ };
+ 43C6E29F0FEFB4EA004B52F7 /* DebugNative */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetviewer;
+ };
+ name = DebugNative;
+ };
+ 43C6E2A00FEFB4EA004B52F7 /* DebugNativeLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetviewer;
+ };
+ name = DebugNativeLeopard;
+ };
+ 43C6E2A10FEFB4EA004B52F7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetviewer;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 43C6E2A20FEFB4EA004B52F7 /* ReleaseLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ossimplanetviewer;
+ };
+ name = ReleaseLeopard;
+ };
+ 4FADC24308B4156D00ABE55E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(inherited)";
+ COPY_PHASE_STRIP = NO;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = "";
+ GCC_OPTIMIZATION_LEVEL = s;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_1)",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_1 = "EXTRA_INFO_STRING_FOR_MENU=\\\"Version\\";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "$(inherited)";
+ OTHER_CPLUSPLUSFLAGS = "$(inherited)";
+ OTHER_LDFLAGS = /usr/lib/libz.dylib;
+ PRODUCT_NAME = ossimPlanet;
+ REZ_SEARCH_PATHS = (
+ "$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+ "$(REZ_SEARCH_PATHS)/**",
+ );
+ USER_HEADER_SEARCH_PATHS = "$(OSSIM_HOME_PATH)/include $(DEV_HOME_PATH)/libwms/include $(DEV_HOME_PATH)/ossimPlanet/include $(UNIV_HEADER_DEP) /usr/X11R6/include/freetype2 /usr/X11R6/include";
+ WARNING_CFLAGS = "-Wall";
+ WRAPPER_EXTENSION = framework;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ 4FADC24408B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(inherited)";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_6)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_7)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_5 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_6 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_7 = "\"$(SRCROOT)/../../../ossim_dependencies/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G4;
+ GCC_OPTIMIZATION_LEVEL = "$(inherited)";
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "$(inherited)";
+ OTHER_CPLUSPLUSFLAGS = "$(inherited)";
+ OTHER_LDFLAGS = "$(inherited)";
+ PRODUCT_NAME = ossimPlanet;
+ REZ_SEARCH_PATHS = (
+ "$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+ "$(REZ_SEARCH_PATHS)/**",
+ );
+ SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+ USER_HEADER_SEARCH_PATHS = "$(inherited)";
+ WARNING_CFLAGS = "-Wall";
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Release;
+ };
+ 4FADC24708B4156D00ABE55E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ ppc,
+ i386,
+ );
+ GCC_MODEL_TUNING = "";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(DEV_HOME_PATH)/ossim/include",
+ "$(DEV_HOME_PATH)/libwms/include",
+ "$(DEV_HOME_PATH)/ossimPlanet/include",
+ "$(UNIV_HEADER_DEP)",
+ );
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = (
+ "-DOSSIMPLANET_ENABLE_PREDATOR",
+ "-DOSSIMPLANET_ENABLE_EPHEMERIS",
+ "-g",
+ );
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ };
+ name = Debug;
+ };
+ 4FADC24808B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 186EECAE0B1CDEF300F7886A /* common_settings.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(inherited)";
+ GCC_MODEL_TUNING = "";
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO;
+ GCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = NO;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = NO;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+ GCC_WARN_ABOUT_POINTER_SIGNEDNESS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = NO;
+ GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = NO;
+ GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO;
+ GCC_WARN_INHIBIT_ALL_WARNINGS = NO;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = NO;
+ GCC_WARN_MISSING_PARENTHESES = NO;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+ GCC_WARN_PEDANTIC = NO;
+ GCC_WARN_PROTOTYPE_CONVERSION = NO;
+ GCC_WARN_SHADOW = NO;
+ GCC_WARN_SIGN_COMPARE = NO;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO;
+ GCC_WARN_UNINITIALIZED_AUTOS = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = NO;
+ GCC_WARN_UNUSED_PARAMETER = NO;
+ GCC_WARN_UNUSED_VALUE = NO;
+ GCC_WARN_UNUSED_VARIABLE = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(DEV_HOME_PATH)/ossim/include",
+ "$(DEV_HOME_PATH)/libwms/include",
+ "$(DEV_HOME_PATH)/ossimPlanet/include",
+ "$(UNIV_HEADER_DEP)",
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ OTHER_CFLAGS = "$(inherited)";
+ OTHER_CPLUSPLUSFLAGS = (
+ "-DOSSIMPLANET_ENABLE_PREDATOR",
+ "-DOSSIMPLANET_ENABLE_EPHEMERIS",
+ "-g",
+ );
+ OTHER_LDFLAGS = "-lz";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+ WARNING_CFLAGS = "-Wall";
+ };
+ name = Release;
+ };
+ EE9D265B0DD888FB005A8951 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ PRODUCT_NAME = All;
+ };
+ name = Debug;
+ };
+ EE9D265C0DD888FB005A8951 /* DebugNative */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = All;
+ };
+ name = DebugNative;
+ };
+ EE9D265D0DD888FB005A8951 /* DebugNativeLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = All;
+ };
+ name = DebugNativeLeopard;
+ };
+ EE9D265E0DD888FB005A8951 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ PRODUCT_NAME = All;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ EE9D265F0DD888FB005A8951 /* ReleaseLeopard */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = All;
+ };
+ name = ReleaseLeopard;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 433A4CD2100CED8D000B969C /* Build configuration list for PBXNativeTarget "ossimplanettest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 433A4CD3100CED8D000B969C /* Debug */,
+ 433A4CD4100CED8D000B969C /* DebugNative */,
+ 433A4CD5100CED8D000B969C /* DebugNativeLeopard */,
+ 433A4CD6100CED8D000B969C /* Release */,
+ 433A4CD7100CED8D000B969C /* ReleaseLeopard */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 43C6E2B00FEFB4F1004B52F7 /* Build configuration list for PBXNativeTarget "ossimplanetklv" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 43C6E2930FEFB4DA004B52F7 /* Debug */,
+ 43C6E2940FEFB4DA004B52F7 /* DebugNative */,
+ 43C6E2950FEFB4DA004B52F7 /* DebugNativeLeopard */,
+ 43C6E2960FEFB4DA004B52F7 /* Release */,
+ 43C6E2970FEFB4DA004B52F7 /* ReleaseLeopard */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 43C6E2B10FEFB4F1004B52F7 /* Build configuration list for PBXNativeTarget "ossimplanetviewer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 43C6E29E0FEFB4EA004B52F7 /* Debug */,
+ 43C6E29F0FEFB4EA004B52F7 /* DebugNative */,
+ 43C6E2A00FEFB4EA004B52F7 /* DebugNativeLeopard */,
+ 43C6E2A10FEFB4EA004B52F7 /* Release */,
+ 43C6E2A20FEFB4EA004B52F7 /* ReleaseLeopard */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "ossimPlanet" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24308B4156D00ABE55E /* Debug */,
+ 18E4E5560BE7802B00C8442B /* DebugNative */,
+ 18A9BCBF0CDA158B00F4581A /* DebugNativeLeopard */,
+ 4FADC24408B4156D00ABE55E /* Release */,
+ 18B28C500CD57AB3008F45B2 /* ReleaseLeopard */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "ossimPlanet" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24708B4156D00ABE55E /* Debug */,
+ 18E4E5570BE7802B00C8442B /* DebugNative */,
+ 18A9BCBE0CDA158B00F4581A /* DebugNativeLeopard */,
+ 4FADC24808B4156D00ABE55E /* Release */,
+ 18B28C4F0CD57AB3008F45B2 /* ReleaseLeopard */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EE9D26650DD88940005A8951 /* Build configuration list for PBXAggregateTarget "All" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EE9D265B0DD888FB005A8951 /* Debug */,
+ EE9D265C0DD888FB005A8951 /* DebugNative */,
+ EE9D265D0DD888FB005A8951 /* DebugNativeLeopard */,
+ EE9D265E0DD888FB005A8951 /* Release */,
+ EE9D265F0DD888FB005A8951 /* ReleaseLeopard */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/ossim-planet.git
More information about the Pkg-grass-devel
mailing list